Experts in Angular

LibrariesParte 2: Angular Package Format (APF)
Angular Package Format

Parte 2: Angular Package Format (APF)

Otimizações

No universo Angular, a performance é um fator crucial para proporcionar uma experiência de usuário excepcional. Uma aplicação lenta e pesada pode frustrar os usuários e comprometer o sucesso da sua missão espacial. Para garantir que sua biblioteca Angular seja leve e rápida, o Angular Package Format oferece uma série de otimizações que a transformam em um foguete pronto para decolar.

Achatamento de Módulos ES: Simplificando a Estrutura da Nave

O Angular Package Format especifica que o código seja publicado no formato de módulo ES “achatado” (Flattened ES Module – FESM). Essa abordagem reduz significativamente o tempo de construção de aplicações Angular, bem como o tempo de download e análise do pacote final.

Imagine que sua biblioteca é uma nave espacial composta por vários módulos, cada um com seus próprios arquivos e dependências. O achatamento de módulos ES combina todos esses módulos em um único arquivo, simplificando a estrutura da nave e tornando-a mais aerodinâmica.

Como Funciona o Achatamento

O compilador Angular pode gerar arquivos de índice de módulo ES. Ferramentas como o Rollup podem usar esses arquivos para gerar módulos achatados em um formato de arquivo FESM.

O FESM é um formato de arquivo criado ao “achatar” todos os módulos ES acessíveis a partir de um ponto de entrada em um único módulo ES. Ele é formado seguindo todas as importações de um pacote e copiando esse código em um único arquivo, preservando todas as exportações ES públicas e removendo todas as importações privadas.

O nome abreviado FESM, pronunciado “fésom”, pode ser seguido por um número, como FESM2020. O número se refere ao nível de linguagem do JavaScript dentro do módulo. Assim, um arquivo FESM2022 seria ESM + ES2022 e incluiria instruções import/export e código-fonte ES2022.

Configurando o Achatamento no tsconfig.json

Para gerar um arquivo de índice de módulo ES achatado, utilize as seguintes opções de configuração no seu arquivo tsconfig.json:

{
  "compilerOptions": {
    // ...
    "module": "esnext",
    "target": "es2022",
    // ...
  },
  "angularCompilerOptions": {
    // ...
    "flatModuleOutFile": "minha-lib-ui.js",
    "flatModuleId": "minha-lib-ui"
  }
}
  • flatModuleOutFile: Especifica o nome do arquivo de índice achatado a ser gerado.
  • flatModuleId: Define um identificador único para o módulo achatado.

Após a geração do arquivo de índice (por exemplo, minha-lib-ui.js) pelo ngc (compilador Angular), ferramentas como o Rollup podem ser usadas para produzir o arquivo FESM final.

Uma Nota sobre os Padrões no package.json: Navegando em Meio às Mudanças

No universo em constante evolução do desenvolvimento web, as ferramentas e tecnologias estão sempre se aprimorando. O Angular Package Format, como um bom navegador, precisa se adaptar a essas mudanças para garantir a compatibilidade e o melhor desempenho possível para suas bibliotecas Angular.

O Caso do Webpack v4: Achatamento Opcional

A partir da versão 4 do webpack, a otimização de achatamento de módulos ES pode não ser mais necessária para usuários do webpack. Em teoria, seria possível obter uma melhor divisão de código (code splitting) sem a necessidade de achatar os módulos.

No entanto, na prática, ainda podem ocorrer regressões de tamanho ao usar módulos não achatados como entrada para o webpack v4. É por isso que as entradas "module" e "es2022" no arquivo package.json ainda apontam para arquivos FESM.

O Futuro do Achatamento: Adaptando-se às Mudanças

A equipe do Angular está investigando essa questão e espera, no futuro, mudar os pontos de entrada "module" e "es2022" para arquivos não achatados, assim que o problema de regressão de tamanho for resolvido.

O Angular Package Format atualmente inclui código ESM2022 não achatado com o propósito de validar essa mudança futura, garantindo que sua biblioteca esteja preparada para as evoluções do ecossistema JavaScript.

Navegando com Flexibilidade

Ao entender as nuances da configuração do package.json e as mudanças em andamento no ecossistema JavaScript, você pode tomar decisões informadas sobre como empacotar sua biblioteca Angular. A flexibilidade do Angular Package Format permite que você se adapte às diferentes ferramentas e fluxos de trabalho, garantindo a compatibilidade e o melhor desempenho possível.

A Flag “sideEffects”: Podando as Árvores da sua Nave Espacial Angular

No universo Angular, a otimização do tamanho do pacote da sua biblioteca é crucial para garantir um desempenho excepcional e uma experiência de usuário fluida. Imagine sua biblioteca como uma nave espacial, onde cada módulo e componente representa uma parte da estrutura. Para tornar essa nave mais leve e ágil, o Angular Package Format utiliza uma técnica poderosa chamada tree-shaking, que remove o código não utilizado do pacote final.

O Que é Tree-Shaking?

O tree-shaking é como um jardineiro espacial que poda as árvores da sua nave, removendo os galhos e folhas que não estão sendo utilizados. Essa técnica analisa as dependências do seu código e identifica quais partes dele são realmente necessárias para o funcionamento da aplicação. Em seguida, ela remove os módulos, funções e outros elementos que não são utilizados, reduzindo significativamente o tamanho do pacote final.

O Desafio dos Efeitos Colaterais

Por padrão, os módulos ES (ECMAScript Modules) são considerados como tendo efeitos colaterais. Isso significa que, ao importar um módulo, qualquer código no nível superior desse módulo será executado, mesmo que você não utilize diretamente nenhum dos seus símbolos exportados.

Em muitos casos, esse comportamento é indesejável, pois a maioria do código com efeitos colaterais em módulos típicos não é realmente necessário para o funcionamento da aplicação. Se esses símbolos não forem importados e usados, é desejável removê-los no processo de otimização, mas os efeitos colaterais podem impedir isso.

A Solução: A Flag sideEffects

Para permitir que as ferramentas de build, como o Webpack, realizem o tree-shaking de forma mais eficiente, o Angular Package Format oferece a flag sideEffects no arquivo package.json. Essa flag permite que você declare se sua biblioteca depende ou não de código com efeitos colaterais no nível superior de seus módulos.

{
  "sideEffects": false 
}

Ao definir sideEffects como false, você está informando às ferramentas de build que sua biblioteca não possui efeitos colaterais no nível superior de seus módulos, dando a elas mais liberdade para realizar o tree-shaking e remover o código não utilizado.

Boas Práticas e Recomendações

A maioria dos pacotes Angular não deve depender de efeitos colaterais de nível superior e, portanto, deve incluir a declaração "sideEffects": false. No entanto, existem alguns casos em que sua biblioteca pode precisar de efeitos colaterais, como:

  • Estilos globais
  • Polyfills
  • Inicialização global

Nesses casos, você deve definir "sideEffects": true ou fornecer um array com os caminhos dos arquivos que possuem efeitos colaterais.

Além disso, é recomendável que você siga o Guia de Estilo do Angular, que naturalmente resulta em código sem efeitos colaterais não locais, facilitando a otimização do seu pacote.

Uma Nave Espacial Leve e Eficiente

Ao utilizar a flag sideEffects e seguir as boas práticas de desenvolvimento Angular, você garante que sua biblioteca seja otimizada ao máximo, com um tamanho de pacote reduzido e um desempenho aprimorado. Essa otimização é crucial para proporcionar uma experiência de usuário fluida e agradável, permitindo que sua nave espacial Angular navegue pelo universo da web com leveza e velocidade.

Nível de Linguagem ES2022: Modernizando a Tecnologia da sua Nave Espacial Angular

No universo em constante evolução do desenvolvimento web, a linguagem JavaScript também passa por atualizações e melhorias constantes. O Angular Package Format, como um bom navegador, acompanha essas mudanças e adota o nível de linguagem ES2022 como padrão para suas bibliotecas.

O Que é o ES2022?

O ES2022 é a versão mais recente da linguagem ECMAScript, que introduz novos recursos e funcionalidades para tornar o desenvolvimento JavaScript mais moderno e eficiente. Alguns dos recursos do ES2022 incluem:

  • Operadores de atribuição lógica: &&=, ||= e ??=, que simplificam a atribuição condicional de valores.
  • Métodos estáticos em classes privadas: Permitem que você defina métodos estáticos em classes privadas, melhorando a organização e o encapsulamento do código.
  • at() para indexação de arrays: Facilita o acesso a elementos em arrays, incluindo o último elemento, utilizando índices negativos.
  • Outras melhorias: O ES2022 também inclui outras melhorias e correções menores na linguagem.

ES2022 como Padrão: Benefícios e Compatibilidade

Ao adotar o ES2022 como nível de linguagem padrão, o Angular CLI garante que sua biblioteca esteja utilizando os recursos mais recentes do JavaScript, proporcionando uma experiência de desenvolvimento mais moderna e produtiva.

No entanto, nem todos os navegadores suportam nativamente todas as funcionalidades do ES2022. Para garantir a compatibilidade com navegadores mais antigos, o Angular CLI realiza um processo de downleveling durante o build da aplicação, convertendo o código ES2022 para uma versão mais antiga do JavaScript que seja suportada por todos os navegadores alvo.

Navegando Rumo ao Futuro

Ao utilizar o nível de linguagem ES2022, você está construindo sua biblioteca Angular com as ferramentas mais modernas e eficientes disponíveis. O Angular CLI se encarrega de garantir a compatibilidade com navegadores mais antigos, permitindo que sua biblioteca seja utilizada em um amplo espectro de ambientes.

Agrupamento de Definições de Tipo (d.ts): Simplificando a Documentação da sua Nave Espacial

No universo TypeScript, as definições de tipo (arquivos .d.ts) são como um manual de instruções detalhado que descreve os componentes, serviços e outros elementos da sua biblioteca Angular. Para facilitar a navegação e a compreensão dessas definições, o Angular Package Format recomenda o uso do API Extractor para agrupar todas as definições de tipo em um único arquivo.

O Problema das Definições de Tipo Fragmentadas

Em versões anteriores do APF, cada ponto de entrada tinha um diretório src ao lado do ponto de entrada .d.ts, e esse diretório continha arquivos .d.ts individuais que correspondiam à estrutura do código-fonte original. Essa abordagem, embora funcional, podia confundir ferramentas como IDEs, que ofereciam autocompletar incorreto, e permitia que os usuários dependessem de caminhos de importação profundos que normalmente não são considerados como parte da API pública de uma biblioteca.

A Solução: API Extractor

A partir da versão 8 do APF, é recomendado utilizar o API Extractor para agrupar as definições de tipo em um único arquivo, simplificando a documentação da sua biblioteca e facilitando sua utilização por outras ferramentas.

O API Extractor analisa seu código TypeScript e gera um único arquivo .d.ts que contém todas as definições de tipo públicas da sua biblioteca. Esse arquivo é então incluído no pacote npm, permitindo que os usuários da sua biblioteca acessem todas as informações de tipo de forma centralizada e organizada.

Benefícios do Agrupamento de Definições de Tipo

  • Clareza e organização: Todas as definições de tipo públicas da sua biblioteca estão em um único arquivo, facilitando a navegação e a compreensão da API.
  • Compatibilidade com ferramentas: O arquivo .d.ts agrupado é compatível com a maioria das IDEs e ferramentas de desenvolvimento, oferecendo recursos como autocompletar e verificação de tipos precisos.
  • Prevenção de importações profundas: Ao agrupar as definições de tipo, você evita que os usuários dependam de caminhos de importação profundos que podem não ser estáveis entre diferentes versões da sua biblioteca.

Um Manual de Instruções Claro e Conciso

Ao utilizar o API Extractor para agrupar suas definições de tipo, você oferece aos usuários da sua biblioteca um manual de instruções claro e conciso, facilitando a compreensão e a utilização dos seus recursos. Essa prática contribui para uma experiência de desenvolvimento mais fluida e produtiva, impulsionando a adoção e o sucesso da sua biblioteca no universo Angular.

Uso do Tslib

A partir da versão 10 do Angular Package Format (APF v10), recomenda-se adicionar o Tslib como uma dependência direta do ponto de entrada principal da sua biblioteca. O Tslib é uma biblioteca auxiliar que contém funções de ajuda para recursos do TypeScript, como classes, heranças, e async/await.

Por que adicionar o Tslib?

  1. Compatibilidade com o TypeScript: O Tslib é uma biblioteca auxiliar para o TypeScript, e a sua versão está vinculada à versão do TypeScript usada para compilar sua biblioteca. Isso significa que, ao adicionar o Tslib como uma dependência direta, você garante que a versão correta seja usada, prevenindo possíveis conflitos ou problemas de compatibilidade.
  2. Redução de Tamanho de Pacote: Ao invés de incluir o código auxiliar do TypeScript diretamente em cada módulo, referenciar o Tslib pode reduzir o tamanho do pacote final. Isso ocorre porque as funções auxiliares do TypeScript são importadas do Tslib, em vez de serem duplicadas em cada módulo que as usa.
  3. Facilidade de Atualização: Com o Tslib como dependência, atualizar o TypeScript em sua biblioteca torna-se mais fácil, já que você pode simplesmente atualizar o Tslib para a versão correspondente.

Como adicionar o Tslib

Para adicionar o Tslib como dependência da sua biblioteca, você deve executar o seguinte comando:

npm install tslib --save

Após a instalação, garanta que a dependência esteja listada no arquivo package.json do seu projeto:

{
  "dependencies": {
    "tslib": "^2.3.0"
  }
}