Ir para o conteúdo
Como melhorar o desempenho de aplicativos Angular?

Como melhorar o desempenho de aplicativos Angular?

Como melhorar o desempenho de Angular aplicativos? Leia esta postagem do blog para encontrar as maneiras – desde a redução de JavaScript e CSS não utilizados até Angular carregamento lento.

8min read

Angular se tornou uma estrutura muito popular e amplamente adotada para o desenvolvimento de aplicativos da Web modernos. Essa tecnologia é muito poderosa e rica em recursos. Tudo Angular o que você precisa como desenvolvedor da Web vem pronto para uso e permite configurar, manter e expandir facilmente qualquer aplicativo criado sobre a estrutura.

E agora, você provavelmente já montou um ou mais aplicativos Angular, mas eles são ideais?

Na Parte 2 da minha série Desempenho de Software, então, falarei sobre otimização de Angular, demonstrando como melhorar o desempenho de um aplicativo Angular usando um aplicativo de exemplo Angular que criei. Usarei o Chrome Dev Tools para derivar uma pontuação inicial do farol para determinar onde o aplicativo está inicialmente. Vamos dar uma olhada no que pode ser melhorado e como.

Outros blogs desta série:

Desempenho de software [Web] Parte I

Como melhorar o desempenho de aplicativos Angular

Para este artigo, usarei um exemplo Angular aplicativo que montei. No momento da redação deste artigo, o aplicativo usa os seguintes recursos e bibliotecas:

  • Angular 16
  • Ignite UI for Angular 16
  • RxJS 7
  • PWA (Angular service worker)
  • Server-side rendering (express server)
  • Angular localization

Angular Build

Tudo parece estar funcionando bem quando estou executando o aplicativo em um ambiente de desenvolvimento, mas a pontuação inicial do farol não é muito alta:

 Lighthouse score with development environment run

Quando olhopara as sugestões para melhorar as seções de pontuação mais baixa, vejo de onde vêm os problemas. Oprimeiro grande problema é o tamanho dos recursos (JavaScript, estilos, recursos estáticos) que são transferidos para o cliente. 

Oportunidades para melhorar o desempenho do aplicativo Angular

Este problema é resolvido facilmente executando uma compilação de produção do meu aplicativo Angular em vez de uma de desenvolvimento. Sempre construa com a configuração de produção antes da implantação. Isso resolverá o aviso para reduzir o tamanho doJavaScripte do CSS.Vamos dar uma olhadano arquivo angular.jsonna raiz do nossorepositório Angular para ver como a compilação de produção difere: 

"configurations": {
  "production": {
    "budgets": [
      {
        "type": "initial",
        "maximumWarning": "2mb",
        "maximumError": "5mb"
      },
      {
        "type": "anyComponentStyle",
        "maximumWarning": "10kb"
      }
    ],
    "fileReplacements": [
      {
        "replace": "projects/common/src/environments/environment.ts",
        "with": "projects/common/src/environments/environment.prod.ts"
      }
    ],
    "localize": true,
    "optimization": true,
    "outputHashing": "all",
    "sourceMap": false,
    "namedChunks": false,
    "extractLicenses": true,
    "vendorChunk": false,
    "buildOptimizer": true,
    "serviceWorker": true,
    "i18nMissingTranslation": "error",
    "ngswConfigPath": "projects/bellumgens/src/ngsw-config.json"
  },
  "bg": {
    "localize": [
      "bg"
    ]
  }
}

muitaconfiguraçãoaqui. Noentanto,o mais importante, neste caso, é aquele"optimization": true.Depois de executar o aplicativo com uma configuração de produção, a diferença na pontuação é significativa em termos de desempenho de tempo de carregamento: 

Pontuação do Lighthouse com build de produção no ambiente de desenvolvimento

Se eu olhar para a lista de oportunidades novamente, o número de sugestões é muito menor. Asmaiores oportunidades listadas em sobre compactação de textosãoJavaScript não utilizado e cache de recursos estáticos:

Oportunidades restantes para melhorias de desempenho

Angular Pre-Rendering and Server-Side Rendering 

Angular é uma estrutura de aplicativo de página única (SPA). Por padrão, o ciclo de vida do aplicativo é tal que, mediante uma solicitação de um cliente, o servidor que hospeda o aplicativo fornece um arquivo HTML que inclui todas as referências de script e estilo necessárias. No entanto, é vazio de conteúdo corporal. Depois que os scripts e estilos são solicitados e servidos, o aplicativo é inicializado e preenchido com conteúdo baseado na lógica JavaScript para o aplicativo fornecido. Angular fornece dois mecanismos para melhorar esse ciclo de vida fornecendo conteúdo real no documento HTML inicial. Para fazer isso, a lógica JavaScript do aplicativo precisa ser executada antes de servir o documento. As maneiras de fazer isso:

  • Ou no momento da compilação (pré-renderização) – para páginas com conteúdo principalmente estático.
  • Ou em tempo de execução no servidor (renderização do lado do servidor) - para páginas com conteúdo mais dinâmico que precisam fornecer conteúdo atualizado em cada solicitação.

Habilitei a renderização do lado do servidor para o aplicativo de exemplo Angular e estou usando o mecanismo expresso para habilitar a compactação de texto e o cache de recursos estáticos. Isso é feito adicionando o seguinte à minha lógica de servidor expresso:

export const app = (lang: string) => {
  // server scaffolded by [ng add @nguniversal/express-engine]
...
  // enable compression [npm install compression]
  const compression = require('compression');
  server.use(compression());
...
  // Serve static files from /browser with 1y caching
  server.get('*.*', express.static(distFolder, {
    maxAge: '1y'
  }));
...
}

Vou servir o aplicativo com renderização do lado do servidor e executar o teste do farol novamente. A carga inicial melhorou ainda mais, trazendo a primeira pintura de conteúdo para menos de um segundo, enquanto o índice de velocidade é reduzido para 1,2 segundos.

Pontuação do Lighthouse com renderização Angular do lado do servidor

As oportunidades restantes para otimização Angular são reduzir JavaScript e CSS não utilizados.

Oportunidades restantes para melhorias de desempenho

Para lidar com isso, terei que fazer alguma refatoração de aplicativos.

Angular Lazy-Loading 

Para reduzir o JavaScript não utilizado, a melhor abordagem seria criar rotas de carregamento lento. Isso informará à estrutura Angular quais componentes não são necessários no módulo de nível superior e dividirá o JavaScript em módulos, cuja lógica é carregada somente quando a rota solicitada é carregada.

O aplicativo de exemplo Angular que estou usando para este blog utiliza componentes maiores, como o igx-grid, que não fazem parte da rota inicial. Estou separando as rotas usando este componente em um módulo separado. Dessa forma, vou carregar esse componente somente depois que as rotas que usam o componente forem carregadas. Depois de separar os módulos, as rotas ficam assim:

export const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'register', component: RegistrationComponent },
  { path: 'unauthorized', redirectTo: 'unauthorized/', pathMatch: 'full' },
  { path: 'unauthorized/:message', component: UnauthorizedComponent },
  { path: 'emailconfirm', component: EmailconfirmComponent },
  { path: 'strategies', loadChildren: () => import('./strategies/strategies.module').then(m => m.StrategiesModule) },
  { path: 'emailconfirm/:error', component: EmailconfirmComponent },
  { path: 'players', loadChildren: () => import('./player-section/player.module').then(m => m.PlayerModule) },
  { path: 'team', loadChildren: () => import('./team-section/team.module').then(m => m.TeamModule) },
  { path: 'notifications', loadChildren: () => import('./notifications/notifications.module').then(m => m.NotificationsModule) },
  { path: 'search/teams/:query', component: TeamResultsComponent },
  { path: 'search/players/:query', component: PlayerResultsComponent },
  { path: '**', component: HomeComponent }
];

É team.module o que carrega a grade que estou usando, então o código para ele se parece com este:

@NgModule({
  imports: [
    CommonModule,
    FormsModule,
    // ...
    IgxGridModule,
    // ...
    TeamComponent,
    // ...
  ]
})
export class TeamModule { }

Olhando para a compilação, este é o resultado da divisão inicial:

Separando o aplicativo Angular em módulos de carregamento lento

Outra coisa que precisa ser feita para melhorar o desempenho do aplicativo Angular é limitar o tamanho do CSS aos estilos usados. Estou usando Ignite UI for Angular como minha biblioteca de interface do usuário e há um ótimo artigo de instruções sobre como personalizar e otimizar os temas dos componentes.

Optimizing Images 

Outro aspecto da otimização Angular que deve ser feito é otimizar as imagens. A verificação do Lighthouse informará se você está usando imagens abaixo do ideal por tipo ou tamanho. Certifique-se de que as imagens carregadas não sejam maiores do que os contêineres em que entram e estejam com codificação ideal. Agora uso o formato .webp para imagens. Reduz um pouco a qualidade, mas, ainda assim, o aplicativo não requer as imagens de maior fidelidade.

As imagens causam mudanças de layout depois de serem carregadas. Portanto, é uma boa ideia definir atributos de largura e altura nas imagens para que o navegador conheça as dimensões antes de carregar as imagens. Se você não tiver configurações de proporção (largura e altura) nas imagens, o Lighthouse irá avisá-lo. Isso reduzirá ou eliminará completamente as mudanças de layout.

NgOptimizedImage to Enforce Image Best Practices 

Angular expõe uma diretiva que impõe as práticas recomendadas de imagem e otimiza o carregamento de imagens para você. Chama-se NgOptimizedImage e é bastante fácil de usar. Tudo o que você precisa fazer é importar CommonModule se ainda estiver em um NgModule aplicativo Angular baseado ou importar NgOptimizedImage no componente em que deseja usá-lo. Em seguida, em vez de usar src para definir o atributo de origem da imagem, você usa ngSrc em vez disso.

<img ngSrc="/assets/wallpapers/strat-editor.webp" width="600" height="347" class="preview-image" alt="Strategy Editor" />

Por fim, vocêpode especificar ainda mais a prioridade de carregamento de cada imagem e instruir o aplicativo a carregar lentamente todas as imagens não críticas. Se eu remover os atributos de largura e altura, o que obtenho executando o aplicativo é:

 NgOptimizedImage enforcing best practices

E é isso.

Embrulhar...

Melhorar o desempenho de aplicativos Angular pode exigir monitoramento contínuo, otimização e práticas recomendadas para garantir que o aplicativo seja executado de forma eficiente e confiável em várias condições. Mas, no final, é assim que você oferece o melhor UX, atrai e retém usuários, mantém a competitividade e alcança o sucesso nos negócios.

Ignite UI for Angular

Solicite uma demonstração