Estratégias de pré-carregamento de rotas no Angular

Pré-carregue as rotas com antecedência para acelerar a navegação dos usuários.

A divisão de código no nível da rota pode ajudar a reduzir o tempo de carregamento inicial de um aplicativo, atrasando o JavaScript associado a rotas que não são inicialmente necessárias. Dessa forma, o roteador do Angular espera até que o usuário navegue até uma determinada rota antes de acionar uma solicitação de rede para fazer o download do JavaScript associado.

Embora essa técnica seja ótima para o carregamento inicial da página, ela pode deixar a navegação mais lenta dependendo da largura de banda e da latência de rede dos usuários. Uma maneira de resolver esse problema é o pré-carregamento de rotas. Com o pré-carregamento, quando o usuário estiver em uma determinada rota, será possível fazer o download do JavaScript associado a rotas que provavelmente serão necessárias a seguir e armazená-lo em cache. O roteador Angular oferece essa funcionalidade prontamente.

Nesta postagem, você vai aprender a acelerar a navegação ao usar a divisão de código no nível da rota aproveitando o pré-carregamento do JavaScript no Angular.

Estratégias de pré-carregamento de rota no Angular

O roteador do Angular fornece uma propriedade de configuração chamada preloadingStrategy, que define a lógica para pré-carregamento e processamento de módulos Angular de carregamento lento. Vamos abordar duas estratégias possíveis:

  • PreloadAllModules, que pré-carrega todas as rotas de carregamento lento, como o nome indica
  • QuicklinkStrategy, que pré-carrega apenas os trajetos associados aos links na página atual.

O restante desta postagem se refere a um app de exemplo do Angular. O código-fonte está disponível no GitHub (em inglês).

Como usar a estratégia PreloadAllModules

O app de exemplo tem várias rotas com carregamento lento. Para pré-carregar todos usando a estratégia PreloadAllModules, integrada ao Angular, especifique como o valor da propriedade preloadingStrategy na configuração do roteador:

import { RouterModule, PreloadAllModules } from '@angular/router';
// …

RouterModule.forRoot([
  …
], {
  preloadingStrategy: PreloadAllModules
})
// …

Agora veicule o aplicativo e observe o painel Network no Chrome DevTools:

  1. Pressione "Control + Shift + J" (ou "Command + Option + J" no Mac) para abrir o DevTools.
  2. Clique na guia Rede.

Você verá que o roteador fez o download de nyan-nyan-module.js e about-about-module.js em segundo plano quando você abriu o aplicativo:

A estratégia PreloadAllModules em ação.

O roteador também registrou as declarações de rota dos módulos para que a transição seja instantânea quando você navegar para um URL associado a qualquer um dos módulos pré-carregados.

PreloadAllModules é útil em muitos casos. No entanto, quando há dezenas de módulos, o pré-carregamento agressivo pode aumentar o uso da rede. Além disso, como o roteador precisa registrar as rotas em todos os módulos pré-carregados, isso pode gerar cálculos intensivos na linha de execução de interface e deixar a experiência do usuário lenta.

A biblioteca de link rápido (link em inglês) oferece uma estratégia melhor para apps maiores. Ela usa a API IntersectionObserver para pré-carregar apenas os módulos associados aos links que estão visíveis na página no momento.

Para adicionar links rápidos a um aplicativo Angular, use o pacote ngx-quicklink. Comece instalando o pacote do npm:

npm install --save ngx-quicklink

Quando estiver disponível no projeto, você poderá usar o QuicklinkStrategy especificando o preloadingStrategy do roteador e importando o QuicklinkModule:

import {QuicklinkStrategy, QuicklinkModule} from 'ngx-quicklink';
…

@NgModule({
  …
  imports: [
    …
    QuicklinkModule,
    RouterModule.forRoot([…], {
      preloadingStrategy: QuicklinkStrategy
    })
  ],
  …
})
export class AppModule {}

Agora, ao abrir o aplicativo novamente, você vai notar que o roteador só pré-carrega nyan-nyan-module.js, porque o botão no centro da página tem um link de roteador. Ao abrir a navegação lateral, você perceberá que o roteador pré-carrega a rota "Sobre":

Uma demonstração da estratégia de pré-carregamento de links rápidos.

O exemplo acima funciona para um aplicativo básico, mas se ele tiver vários módulos de carregamento lento, será necessário importar o QuicklinkModule para um módulo compartilhado, exportá-lo e importá-lo para os módulos de carregamento lento.

Primeiro, importe o QuicklinkModule de ngx-quicklink para seu módulo compartilhado e exporte-o:

import { QuicklinkModule } from 'ngx-quicklink';
…

@NgModule({
  …
  imports: [
    QuicklinkModule
  ],
  exports: [
    QuicklinkModule
  ],
  …
})
export class SharedModule {}

Em seguida, importe SharedModule para todos os módulos de carregamento lento:

import { SharedModule } from '@app/shared/shared.module';
…

@NgModule({
  …
  imports: [
      SharedModule
  ],
  …
});

Agora, Quicklinks vai estar disponível nos módulos com carregamento lento.

Além do pré-carregamento básico

Embora o pré-carregamento seletivo via link rápido possa acelerar significativamente a navegação, é possível tornar sua estratégia de pré-carregamento ainda mais eficiente em rede usando o pré-carregamento preditivo, que é implementado pelo Guess.js. Ao analisar um relatório do Google Analytics ou de outro provedor de análises, a Guess.js pode prever a jornada de navegação de um usuário e pré-carregar apenas os blocos JavaScript que provavelmente serão necessários a seguir.

Saiba como usar o Guess.js com o Angular nesta página do site Guess.js.

Conclusão

Para acelerar a navegação ao usar a divisão de código no nível do trajeto:

  1. Escolha a estratégia de pré-carregamento correta de acordo com o tamanho do aplicativo:
    • Aplicativos com poucos módulos podem usar a estratégia PreloadAllModules integrada do Angular.
    • Aplicativos com muitos módulos devem usar uma estratégia de pré-carregamento personalizada, como o link rápido do Angular, ou o pré-carregamento preditivo, conforme implementado no Guess.js.
  2. Configure a estratégia de pré-carregamento definindo a propriedade preloadStrategy do roteador do Angular.