Estrategias de precarga de rutas en Angular

Precarga las rutas con anticipación para mejorar la velocidad de la navegación de los usuarios.

La división de código a nivel de la ruta puede ayudarte a reducir el tiempo de carga inicial de una aplicación retrasando el código JavaScript asociado con las rutas que no son necesarias inicialmente. De esta manera, el router de Angular espera hasta que un usuario navegue a una ruta determinada antes de activar una solicitud de red para descargar el código JavaScript asociado.

Si bien esta técnica es excelente para la carga inicial de la página, puede ralentizar la navegación, según la latencia y el ancho de banda de la red de los usuarios. Una forma de abordar este problema es la carga previa de rutas. Con la carga previa, cuando el usuario está en una ruta determinada, puedes descargar y almacenar en caché el código JavaScript asociado con las rutas que es probable que se necesiten a continuación. El router de Angular proporciona esta funcionalidad de forma predeterminada.

En esta publicación, aprenderás a acelerar la navegación cuando uses la división de código a nivel de la ruta aprovechando la carga previa de JavaScript en Angular.

Estrategias de carga previa de rutas en Angular

El router de Angular proporciona una propiedad de configuración llamada preloadingStrategy, que define la lógica para la carga previa y el procesamiento de módulos de Angular cargados de forma diferida. Abordaremos dos estrategias posibles:

  • PreloadAllModules, que precarga todas las rutas cargadas de forma diferida, como su nombre lo indica
  • QuicklinkStrategy, que precarga solo las rutas asociadas con los vínculos de la página actual.

El resto de esta publicación se refiere a una app de ejemplo de Angular. Puedes encontrar el código fuente en GitHub.

Usa la estrategia de PreloadAllModules

La app de ejemplo tiene varias rutas cargadas de forma diferida. Para precargarlos todos con la estrategia PreloadAllModules, que está integrada en Angular, especifícala como el valor de la propiedad preloadingStrategy en la configuración del router:

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

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

Ahora, entrega la aplicación y observa el panel Red en Chrome DevTools:

  1. Presiona "Control + Mayúsculas + J" (o "Comando + Opción + J" en Mac) para abrir DevTools.
  2. Haga clic en la pestaña Red.

Deberías ver que el router descargó nyan-nyan-module.js y about-about-module.js en segundo plano cuando abriste la aplicación:

La estrategia PreloadAllModules en acción.

El router también registró las declaraciones de ruta de los módulos para que, cuando navegues a una URL asociada con cualquiera de los módulos precargados, la transición sea instantánea.

PreloadAllModules es útil en muchos casos. Sin embargo, cuando tienes decenas de módulos, su carga previa agresiva puede aumentar mucho el uso de la red. Además, como el router debe registrar las rutas en todos los módulos precargados, puede provocar cálculos intensivos en el subproceso de IU y generar una experiencia del usuario lenta.

La biblioteca de vínculos directos proporciona una mejor estrategia para apps más grandes. Usa la API de IntersectionObserver para precargar solo los módulos asociados con los vínculos que son visibles en la página.

Puedes agregar un vínculo rápido a una app de Angular con el paquete ngx-quicklink. Comienza instalando el paquete desde npm:

npm install --save ngx-quicklink

Una vez que esté disponible en tu proyecto, puedes usar QuicklinkStrategy especificando el preloadingStrategy del router y, luego, importando el QuicklinkModule:

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

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

Ahora, cuando vuelvas a abrir la aplicación, notarás que el router solo carga previamente nyan-nyan-module.js, ya que el botón en el centro de la página tiene un vínculo al router. Cuando abras la navegación lateral, verás que el router precarga la ruta "Acerca de":

Una demostración de la estrategia de carga previa de vínculos rápidos.

El ejemplo anterior funcionará para una aplicación básica, pero si tu aplicación contiene varios módulos cargados de forma diferida, deberás importar QuicklinkModule en un módulo compartido, exportarlo y, luego, importarlo en tus módulos cargados de forma diferida.

Primero, importa el QuicklinkModule de ngx-quicklink a tu módulo compartido y expórtalo:

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

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

Luego, importa tu SharedModule a todos tus módulos cargados de forma diferida:

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

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

Quicklinks ahora estará disponible en tus módulos cargados de forma diferida.

Más allá de la carga previa básica

Si bien la carga previa selectiva a través de un vínculo rápido puede acelerar significativamente la navegación, puedes hacer que tu estrategia de carga previa sea aún más eficiente en la red con la carga previa predictiva, que implementa Guess.js. A través del análisis de un informe de Google Analytics o de otro proveedor de estadísticas, Guess.js puede predecir el recorrido de navegación de un usuario y precargar solo los fragmentos de JavaScript que es probable que se necesiten a continuación.

Puedes aprender a usar Guess.js con Angular en esta página del sitio de Guess.js.

Conclusión

Para acelerar la navegación cuando se usa la división de código a nivel de la ruta, haz lo siguiente:

  1. Elige la estrategia de carga previa adecuada según el tamaño de tu aplicación:
    • Las aplicaciones con pocos módulos pueden usar la estrategia PreloadAllModules integrada de Angular.
    • Las aplicaciones con muchos módulos deben usar una estrategia de carga previa personalizada, como el vínculo rápido de Angular o la carga previa predictiva, como se implementa en Guess.js.
  2. Para configurar la estrategia de carga previa, establece la propiedad preloadStrategy del router de Angular.