Angular Schematics — Criando Projetos Customizados
Introdução
É muito comum realizarmos a criação de projetos Angular seguindo algum tipo de estrutura padrão de pastas ou até mesmo com a utilização de alguns arquivos de base, uma forma de evitar repetir todo o processo em projetos novos e melhorar a produtividade é utilizando os Schematics do Angular.
O Angular Schematics foi introduzido pela equipe Angular em 2018 e fornece uma API para gerar e gerenciar arquivos em seu projeto Angular, além de fornecer todas as dependências necessárias. Pense nisso como uma ferramenta de templates.
Suponhamos que seja bem comum que você e/ou seu time realize a criação de projetos que seguem a estrutura abaixo.
Iremos realizar a criação de um schematics que estende do ng new
padrão do angular e irá criar exatamente essa estrutura.
Criando Uma Collection de Schematics
Primeiro, certifique-se de ter o Node 6.9 ou superior instalado. Em seguida, instale a CLI do Schematics de forma global.
npm install -g @angular-devkit/schematics-cli
Com Isso agora temos acessos a CLI do schematics , que você pode usar para criar uma nova collection em branco:
schematics blank mdn-schematics
Aqui temos a propriedade schematics
do arquivo collection.json
que armazena todas as schematics que podemos ter no projeto.
Note que temos uma propriedade que declara o nome da nossa schematics e na propriedade factory
indicamos o caminho para o arquivo onde está a schematic e qual método devemos executar deste arquivo indicado após o simbolo de #
.
As Partes de um Schematics
Após passar algum tempo construindo seu próprio Schematics, você perceberá que um Schematics é composto pelos seguintes arquivos.
collection.json
- Arquivo de definições de 1 ou mais Schematics.index.ts
- Arquivo que contem o código de implementação da Schematic.schema.json
- Arquivo que define os tipos e valores padrão das variáveis usadas pelo schematic.schema.d.ts
- Arquivo com as tipagens do Schema.files/
- Arquivos que servirão como templates a serem replicados.
Tipos Básicos
- O objeto
Tree
é a representação virtual estruturada de cada arquivo do workspace ao qual aplicamos o schematics. Em um Schematics você não executa nenhuma ação direta no sistema de arquivos.
Em vez disso, você descreve quais modificações gostaria de aplicar a umaTree
, ao fazer modificações, você não altera a base, mas adiciona essas modificações àstaging area
, que posteriormente são aplicadas a base. - O objeto
Rule
é uma função que é invocada recebendo umaTree
e umSchematicContext
. O objetoRule
geralmente é utilizado para fazer alterações em umaTree
e retornar essaTree
alterada. - O objeto
SchematicContext
fornece acesso a funções utilitárias e metadados com os quais o schematic pode precisar trabalhar, incluindo uma API de logs para ajudar no processo de debug. Este objeto também define uma estratégia de mesclagem que determina como as alterações são mescladas daTree
atual naTree
base. Uma mudança pode ser aceita ou ignorada, ou lançar uma exceção.
Integrando ao ng-new
Para que seja possível que nossa schematics seja executada durante o ng new do usuário precisamos alterar a chave do nome da schematics para ng-new, vamos aproveitar e também alterar o nome do método a ser executado para main e acrescentar um log para realizarmos um teste de execução.
Para realizar-mos o nosso primeiro teste devemos fazer o build do projeto com o comando npm run build
para evitar ficar executando este script a todo momento, acrescente mais 1 script no package.json, para rebuildar o projeto a medida que alterações forem feitas.
"watch": "tsc -p tsconfig.json --watch"
agora com o comando schematics .:ng-new
da schematics CLI podemos testar a nossa schematics
Veja que foi executado o log com sucesso, sinal que nossa schematics já esta funcionando, apesar de não realizar nenhuma modificação ainda.
Recebendo Inputs do Usuário
Para que possamos receber e utilizar dados passados pelo o usuário via terminal, iremos criar um arquivo chamado schema.json
dentro da pasta da nossa schematics, no nosso caso mdn-schematics.
Nesse arquivo podemos definir os tipos das variáveis a serem passadas na propriedade properties
e perguntas a serem exibidas para o usuário no terminal, utilizando as propriedades x-prompt
.
Nesse caso estamos definindo uma propriedade name
do tipo string
que é obrigatória ser passada pelo usuário.
O valor da propriedade x-prompt
é a mensagem que o schematics usará para solicitar um valor ao usuário, se ele não fornecer um. Com a proriedade $default
é possível definir um valor padrão. Nesse caso, o valor padrão será o primeiro argumento que o usuário passar na linha de comando.
Também é necessário acescentar a propriedade schema com o caminho para o schema no arquivo collection.json
Dessa forma, poderemos usar nosso schematics de três maneiras.
1 - Apenas chamando o schematics, sem passar nada. O schematics irá pedir um nome, exibindo a mensagem que definimos na propriedade x-prompt
.
2 - Chamando o schematic passando a flag name
e seu valor.
3 - Chamando o schematics passando apenas um valor como argumento.
Com isso também podemos criar um interface para representar a estrutura dos parâmetros passados para a nossa função main
.
Executando uma Schematic externa
Agora que ja sabemos como receber paramêtros do nosso usuário, não iremos querer reinventar a roda e realizar toda a criação de um projeto Angular do 0 novamente, para isso iremos reutilizar a schematics ng-new
do proprio Angular, e já definir algumas opções por padrão.
Para isso iremos criar um função chamada runNgNewSchematic
que irá utilizar de uma função chamada externalSchematic
do pacote @angular-devkit/schematics passando o name
que recebemos como parâmetro e definindo outras opções por padrão.
Também será necessário instalar o pacote @schematics/angular
e informar no arquivo collection.json
que iremos estender o schematics do angular.
Agora ao executar a nossa schematics, o ng-new
padrão do angular também será chamado.
Explorando a Schematic API
A API do Schematics fornece muitas funções e objetos utilitários para manipular arquivos e pastas.
O objeto Tree
tem um método create, mas apenas para criação de arquivos. Como transformar isso em nossa vantagem para criar uma pasta?
Você conhece o arquivo .gitkeep
? Quando você cria um diretório vazio, o Git não o versiona. Ao adicionar este arquivo .gitkeep
notificará o git para versioná-lo. Então, este é o truque: criar um .gitkeep é a chave para gerar uma pasta vazia!
Agora podemos criar uma função que ira manipular a Tree
e criar todas as pastas padrões necessárias do nosso projeto.
Aqui estamos utilizando o método chain que faz a combinação de multiplas Rules em apenas 1.
Ao executar nossa schematics novamente veremos que as pastas agora foram criadas.
Mas e a pasta sass mostrada no ínicio com aqueles partial files?
Angular Schematic Template Files
Sim, você pode codar um schematics inteiro apenas no arquivo index.ts. No entanto, é mais útil e eficiente trabalhar com arquivos de modelo que podemos apenas injetar variáveis se necessário (que não será o nosso caso) e cuspir código. Então, a primeira coisa que precisamos fazer é adicionar uma pasta files
em src/mdn-schematics
e colocar os arquivos de modelo lá.
Agora iremos realizar a criação de mais uma função no index.ts
que ira criar essa pasta com todos esses arquivos durante a execução do schematics.
Aqui estamos utilizando as função apply
que é responsável por aplicar multiplas Rules
(segundo parâmetro) a um Source
(primeiro parâmetro) e retornar o mesmo transformado.
Com a função url
criamos um objeto Source
a partir do endereço de uma pasta, e no segundo parâmetro estamos utilizando a função move
para aplicar uma Rule
que move os templates para o nosso camimnho esperado.
Agora ao exercutarmos novamente a nossa schematics teremos a pasta sass criada com os arquivos de template.
Publicando no NPM
Agora podemos realizar a publicação da nossa schematics no npm
usando o comando npm publish
E com isso temos a nossa schematic publicada no npm.
Para realizar a utilização da schematics é necessário instalar o pacote de forma global npm i -g mdn-schematics
e executa-la junto com o comando do angular ng new -c=mdn-schematics
.
Referências:
- https://angular.io/guide/schematics
- https://javascript-conference.com/blog/how-to-create-your-own-angular-schematics/
Espero que isso seja útil para você e até a próxima.
O projeto utilizado neste artigo pode ser encontrado neste repositório do GitHub.
E o schematics publicado pode ser acessado npm.