
Quando os projetos se tornam um pouco mais de um, é necessário reutilizar de alguma forma não apenas módulos individuais com código, mas também os próprios componentes da interface do usuário. Existem muitas opções para solucionar o problema - desde copiar e colar tradicional até configurar um projeto separado com testes, documentação e até blackjack.
O problema é que a segunda opção exige esforços significativos de preparação e cada projeto é único - com suas próprias ferramentas nas quais cada novo desenvolvedor precisa lidar com ele novamente. No final de julho, a equipe Angular propôs uma solução própria e abrangente para esse problema, adicionando ao angular / cli um novo comando para criar bibliotecas - biblioteca.
Vamos ver o que aconteceu.
Para os testes, a última versão estável do angular / cli foi realizada - 6.1.5 (09/04/2018)
Mundo perfeito
Em um mundo ideal, tudo deve ser conveniente. Então, para a biblioteca de componentes, eu destacaria três pontos importantes
- Uniformidade de projetos e início rápido
- Conveniência de desenvolvimento
- Facilidade de distribuição
Então, vamos começar do começo.
Para criar nossa própria biblioteca, precisamos dar dois passos - criar um novo projeto e adicionar uma biblioteca a ele. Primeiro, crie um novo projeto:
npx @angular/cli@latest new mylibapp
npxEu uso o npx para não instalar o cli globalmente e evitar construções de execução do npm. Se você possui o npm versão 5.2 ou posterior, tente. Leia mais aqui
Após a execução do comando, veremos um projeto padrão (para 6 angulares, que difere da 5ª versão) no qual serão criados dois subprojetos - o principal mylibapp e mylibapp-e2e. O próprio projeto angular agora é descrito em angular.json.

Ainda não existem bibliotecas.
E aqui está ele a primeira advertência. Nosso nome já foi escolhido pelo projeto principal e o nome da biblioteca também não funcionará. Portanto, se você deseja nomear a biblioteca como minha super-biblioteca, primeiro é necessário criar um projeto, que deve ser chamado de alguma forma diferente. Por exemplo, meu-super-biblioteca-projeto. E só então, crie uma biblioteca com o nome desejado.
Agora crie um terceiro subprojeto e gere uma biblioteca.
cd mylibapp npx ng generate library mylib
Não é necessário especificar um prefixo, mas é muito desejável não se cruzar com outras bibliotecas.

Como você pode ver, agora, nossa terceira biblioteca foi adicionada como o terceiro subprojeto. Possui seu próprio pacote separado.json, tsconfig e karma.conf.js, que permite configurá-lo sem medo de prejudicar outros projetos. A propósito, se desejado, podemos adicionar outra biblioteca e também será um subprojeto separado. Mas é por isso que a biblioteca não pôde ser distinguida por um projeto completamente separado (como em .Net) que eu não conheço. E se o projeto e2e não for difícil de remover manualmente, o projeto principal não estará mais lá. Como resultado, um código extra aparece no repositório, o que não é muito bom.
Agora vamos ver quais ferramentas obtemos imediatamente. Este é um monte de tslint + codelyzer, karma + jasmim e transferidor para e2e. I.e. conjunto padrão de projeto angular, nada específico para a biblioteca que não fomos trazidos. Isso é um pouco estranho, pois algumas ferramentas para visualizar componentes e transformá-los em documentação (como um livro de histórias ) são simplesmente necessárias. Mas tudo bem, vamos assumir que aqui eles simplesmente nos deixaram espaço para manobras.
Vamos executar os testes e o linter para garantir que tudo funcione.
npm test mylib npx ng lint mylib
Tudo correu bem para mim, mas o Chrome foi usado para testes, o que também é estranho. Não tenho nada contra ele, mas em servidores de compilação não será 90%. Por que eles não usaram o mesmo marionetista não está claro.
Para resumir:
Prós
- Início rápido de um novo projeto
- Abordagem uniforme
Contras
- Código extra no projeto
- Coisas óbvias precisam ser concluídas com as mãos.
Até agora, nada crítico, continuamos a cavar mais.
Desenvolvimento
Já temos alguns componentes prontos, vamos dar uma olhada neles. Como não temos nenhuma ferramenta especial, usaremos o projeto principal (aqui se mostra por que é necessário). Para fazer isso, precisamos construir a biblioteca, importar o módulo da biblioteca e iniciar o projeto principal.
algum código npx ng build mylib
import { MylibModule } from "mylib"; ... @NgModule({ declarations: [ AppComponent, ], imports: [ BrowserModule, MylibModule ], providers: [], bootstrap: [AppComponent] })
npm start
Depois que tudo estiver pronto, veremos nosso componente da biblioteca. Mas, novamente, há uma nuance - o modo de observação da biblioteca ainda não foi concluído. Você precisa executar a construção da biblioteca a cada vez? O relógio aparecerá apenas em angular / cli 6.2+. E não fora da caixa, para isso você terá que adicionar um novo sinalizador no tsconfig.json
tsconfig.json
"angularCompilerOptions": { "enableResourceInlining": true, }
E, em seguida, execute a compilação com a bandeira de observação:
ng build mylib
Se, por algum motivo, você usar o cli na versão 6.2, precisará construí-lo, o que, francamente, é ruim.
Agora vamos adicionar um novo componente. Para fazer isso, execute o comando padrão generate component. Devido ao fato de a biblioteca não ser nosso projeto principal, você deve usar o sinalizador do projeto, o que também é um pouco chato (mas se a biblioteca for uma solução independente ...).
npx ng generate component some-nice-image
Agora, em mylib / src, crie a pasta assets, adicione uma imagem e reconstrua a biblioteca novamente para ver o resultado. E então outra surpresa nos espera - não há imagem. Acontece que os recursos usados na biblioteca não entram automaticamente na compilação, é necessário copiá-los você mesmo (ou assim ). E parece não ser assustador, mas ainda assim não está certo.
Mas tremer as árvores deve funcionar imediatamente. Vamos criar outro componente na biblioteca, mas não o usaremos no projeto principal. Montando o projeto principal no modo de produção
npx build
E vemos que o tamanho do pacote não mudou. A trepidação de árvores realmente funciona com bibliotecas!
Agora, seria bom tentar criar algum tipo de dependência. Como cada projeto possui seu próprio package.json, precisamos primeiro ir para a pasta library e executar o comando npm install
npm i -D @drag13/when-do npm i @drag13/round-to
Eu deliberadamente os coloquei de maneiras diferentes para verificar como o empacotador lidaria com isso mais tarde. Tudo está definido sem problemas. Tentamos coletar e receber um aviso
Distribuir pacotes npm com 'dependências' não é recomendado. Considere adicionar drag13 / round-to a 'peerDependencies' ou removê-lo de 'dependencies
Distribuir pacotes de dependência do npm não é desejável. Considere adicionar dependência de drag13 / round-to a peerDependencies ou até removê-lo das dependências
e então o erro:
A dependência drag13 / round-to deve estar explicitamente na lista de permissões
A dependência drag13 / round-to deve ser explicitamente adicionada à lista de permissões.
Isso já é interessante, por design, a biblioteca não deseja ter dependências diretas. Estamos tentando mudar nosso vício para a seção peerDependencies e remontar - pronto, tudo funciona. Mas isso significa que a ordem de instalação das bibliotecas de terceiros agora é diferente. Primeiro, coloque a dependência no módulo principal e adicione as canetas à seção peerDependencies da biblioteca com canetas.
O restante funciona da mesma forma que em um projeto Angular regular.
Para resumir brevemente:
Prós:
- Trabalhamos em um ambiente familiar com equipes familiares
- Há tremores de árvores fora da caixa
Contras:
- Para "ver o componente", você precisa usar o projeto inteiro
- Ainda não há modo de exibição
- Os recursos precisam ser copiados manualmente ou para configurar você mesmo o processo de compilação.
E, finalmente, vá para a publicação
Postagem
Está tudo bem aqui. Angular / cli usa o ng-packgr bem estabelecido para publicar, que compila independentemente nosso código em um pacote adequado para publicação npm, deixando de fora a configuração do arquivo package.json (que não é pequena), a minificação, o empacotamento em diferentes formatos (por exemplo, em UMD) .
Para publicar seu pacote (ou ver o que há dentro), você precisa executar três comandos
npx ng build
Se você não deseja publicar, substitua o comando de publicação pelo pacote
Como resultado, obtive o seguinte:

Primeiro, vamos dar uma olhada no package.json, que parece bem diferente do package.json original da nossa biblioteca.

Como você pode ver, o packagr não excluiu nossas devDependencies, embora algumas o façam. Além disso, teoricamente satisfeito com o número de formatos descritos em package.json (embora eu não conheça metade deles).
Dentro do pacote, há um pacote compactado e não minificado no formato UMD e vários outros pacotes do formato interno angular (fesm5, fesm2015). Mas, o mais importante, agora a cabeça dos desenvolvedores não vai doer com isso, o que é simplesmente maravilhoso.
Vamos passar para as conclusões.
Prós:
Total
A solução foi interessante, mas bruta. O início e a publicação são muito convenientes, mas ainda há questões para o desenvolvimento. É especialmente frustrante que agora a biblioteca não seja um projeto independente por design, mas uma adição ao projeto principal com a possibilidade de publicação.
Por outro lado, uma grande parte do trabalho foi realizada, a funcionalidade está em constante evolução e tenho certeza de que, com o tempo, obteremos uma excelente ferramenta para o desenvolvimento.