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

Pré-carregue rotas com antecedência para agilizar 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 necessárias inicialmente. Dessa forma, o roteador Angular aguarda até que um usuário navegue para 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 desacelerar a navegação, dependendo da latência e da largura de banda da rede dos usuários. Uma maneira de resolver esse problema é o carregamento prévio de rotas. Com o pré-carregamento, quando o usuário está em uma determinada rota, é possível fazer o download e armazenar em cache o JavaScript associado a rotas que provavelmente serão necessárias em seguida. O roteador Angular oferece essa funcionalidade pronto para uso.

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

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

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

  • PreloadAllModules, que carrega previamente todas as rotas carregadas com lentidão, como o nome indica
  • QuicklinkStrategy, que carrega previamente apenas as rotas associadas aos links na página atual.

O restante desta postagem se refere a um app Angular de exemplo. O código-fonte está disponível no GitHub.

Como usar a estratégia PreloadAllModules

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

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

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

Agora, forneça o aplicativo e observe o painel Network no Chrome DevTools:

  1. Pressione "Control+Shift+J" (ou "Command+Option+J" no Mac) para abrir as Ferramentas do desenvolvedor.
  2. Clique na guia Rede.

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, quando você navegasse para um URL associado a qualquer um dos módulos pré-carregados, a transição fosse instantânea.

O PreloadAllModules é útil em muitos casos. No entanto, quando você tem dezenas de módulos, o carregamento prévio agressivo pode aumentar muito o uso da rede. Além disso, como o roteador precisa registrar as rotas em todos os módulos pré-carregados, ele pode causar cálculos intensos na linha de execução da interface e levar a uma experiência do usuário lenta.

A biblioteca quicklink oferece uma estratégia melhor para apps maiores. Ele usa a API IntersectionObserver para pré-carregar apenas os módulos associados a links que estão visíveis na página.

É possível adicionar um link rápido a um app Angular usando o pacote ngx-quicklink. Comece instalando o pacote do npm:

npm install --save ngx-quicklink

Quando ele estiver disponível no seu projeto, será possível usar 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, quando você abrir o aplicativo novamente, vai notar que o roteador só carrega nyan-nyan-module.js, já que o botão no centro da página tem um link para o roteador. Ao abrir a navegação lateral, você vai notar que o roteador carrega previamente 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 o aplicativo tiver vários módulos carregados de forma lenta, será necessário importar o QuicklinkModule em um módulo compartilhado, exportá-lo e importar o módulo compartilhado nos módulos carregados de forma lenta.

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

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

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

Em seguida, importe o SharedModule para todos os módulos carregados de forma lenta:

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

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

Quicklinks agora vai estar disponível nos módulos carregados de forma lenta.

Indo além do pré-carregamento básico

Embora o carregamento prévio seletivo por quicklink possa acelerar significativamente a navegação, você pode tornar sua estratégia de carregamento prévio ainda mais eficiente na rede usando o carregamento prévio preditivo, que é implementado pelo Guess.js. Ao analisar um relatório do Google Analytics ou de outro provedor de análise, o Guess.js pode prever a jornada de navegação de um usuário e pré-carregar apenas os blocos de JavaScript que provavelmente serão necessários em seguida.

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

Conclusão

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

  1. Escolha a estratégia de pré-carregamento certa 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 precisam usar uma estratégia de pré-carregamento personalizada, como o quicklink do Angular ou o pré-carregamento preditivo, conforme implementado no Guess.js.
  2. Defina a estratégia de pré-carregamento definindo a propriedade preloadStrategy do roteador do Angular.