Usa la división de código a nivel de la ruta para mejorar el rendimiento de tu app.
En esta publicación, se explica cómo configurar la división de código a nivel de la ruta en una aplicación de Angular, lo que puede reducir el tamaño del paquete de JavaScript y mejorar de forma significativa el tiempo de interacción.
Puedes encontrar las muestras de código de este artículo en GitHub. El ejemplo de enrutamiento anticipado está disponible en la rama anticipada. El ejemplo de división de código a nivel de la ruta se encuentra en la rama diferida.
Por qué es importante la división de código
La complejidad cada vez mayor de las aplicaciones web ha provocado un aumento significativo en la cantidad de JavaScript que se envía a los usuarios. Los archivos JavaScript grandes pueden retrasar notablemente la interactividad, por lo que pueden ser un recurso costoso, en especial en dispositivos móviles.
La forma más eficiente de reducir los paquetes de JavaScript sin sacrificar funciones en tus aplicaciones es implementar una división de código agresiva.
La división de código te permite dividir el código JavaScript de tu aplicación en varios fragmentos asociados con diferentes rutas o funciones. Este enfoque solo envía a los usuarios el código JavaScript que necesitan durante la carga inicial de la aplicación, lo que mantiene bajos los tiempos de carga.
Técnicas de división de código
La división de código se puede realizar en dos niveles: el nivel de componente y el nivel de ruta.
- En la división de código a nivel del componente, mueves los componentes a sus propios fragmentos de JavaScript y los cargas de forma diferida cuando se necesitan.
- En la división de código a nivel de la ruta, encapsulas la funcionalidad de cada ruta en un fragmento independiente. Cuando los usuarios navegan por tu aplicación, recuperan los fragmentos asociados con las rutas individuales y obtienen la funcionalidad asociada cuando la necesitan.
Esta publicación se enfoca en configurar la división a nivel de la ruta en Angular.
Aplicación de ejemplo
Antes de analizar cómo usar la división de código a nivel de la ruta en Angular, veamos una app de ejemplo:
Revisa la implementación de los módulos de la app. Dentro de AppModule
, se definen dos rutas: la predeterminada asociada con HomeComponent
y una nyan
asociada con NyanComponent
:
@NgModule({
...
imports: [
BrowserModule,
RouterModule.forRoot([
{
path: '',
component: HomeComponent,
pathMatch: 'full'
},
{
path: 'nyan',
component: NyanComponent
}
])
],
...
})
export class AppModule {}
División de código a nivel de la ruta
Para configurar la división de código, se debe refactorizar la ruta de acceso anticipada nyan
.
La versión 8.1.0 de Angular CLI puede hacer todo por ti con este comando:
ng g module nyan --module app --route nyan
Esto generará lo siguiente:
- Un nuevo módulo de enrutamiento llamado NyanModule
- Una ruta en AppModule
llamada nyan
que cargará de forma dinámica NyanModule
- Una ruta predeterminada en NyanModule
- Un componente llamado NyanComponent
que se renderizará cuando el usuario ingrese a la ruta predeterminada
Analicemos estos pasos de forma manual para comprender mejor la implementación de la división de código con Angular.
Cuando el usuario navegue a la ruta nyan
, el router renderizará el NyanComponent
en el tomacorriente del router.
Para usar la división de código a nivel de la ruta en Angular, establece la propiedad loadChildren
de la declaración de ruta y combínala con una importación dinámica:
{
path: 'nyan',
loadChildren: () => import('./nyan/nyan.module').then(m => m.NyanModule)
}
Existen dos diferencias clave con respecto a la ruta de acceso anticipada:
- Estableciste
loadChildren
en lugar decomponent
. Cuando usas la división de código a nivel de la ruta, debes apuntar a módulos cargados de forma dinámica, en lugar de componentes. - En
loadChildren
, una vez que se resuelve la promesa, devuelves elNyanModule
en lugar de apuntar aNyanComponent
.
En el fragmento anterior, se especifica que, cuando el usuario navega a nyan
, Angular debe cargar nyan.module
de forma dinámica desde el directorio nyan
y renderizar el componente asociado con la ruta predeterminada declarada en el módulo.
Puedes asociar la ruta predeterminada con un componente mediante esta declaración:
import { NgModule } from '@angular/core';
import { NyanComponent } from './nyan.component';
import { RouterModule } from '@angular/router';
@NgModule({
declarations: [NyanComponent],
imports: [
RouterModule.forChild([{
path: '',
pathMatch: 'full',
component: NyanComponent
}])
]
})
export class NyanModule {}
Este código renderiza NyanComponent
cuando el usuario navega a https://example.com/nyan
.
Para verificar que el router de Angular descargue nyan.module
de forma diferida en tu entorno local, haz lo siguiente:
- Presiona "Control + Mayúsculas + J" (o "Comando + Opción + J" en Mac) para abrir DevTools.
Haga clic en la pestaña Red.
Haz clic en NYAN en la app de ejemplo.
Ten en cuenta que el archivo
nyan-nyan-module.js
aparece en la pestaña de red.
Encuentra este ejemplo en GitHub.
Cómo mostrar un ícono giratorio
En este momento, cuando el usuario hace clic en el botón NYAN, la aplicación no indica que está cargando JavaScript en segundo plano. Para proporcionar comentarios al usuario mientras se carga la secuencia de comandos, es probable que desees agregar un ícono giratorio.
Para ello, comienza por agregar el marcado del indicador dentro del elemento router-outlet
en app.component.html
:
<router-outlet>
<span class="loader" *ngIf="loading"></span>
</router-outlet>
Luego, agrega una clase AppComponent
para controlar los eventos de enrutamiento. Esta clase establecerá la marca loading
en true
cuando escuche el evento RouteConfigLoadStart
y establecerá la marca en false
cuando escuche el evento RouteConfigLoadEnd
.
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
loading: boolean;
constructor(router: Router) {
this.loading = false;
router.events.subscribe(
(event: RouterEvent): void => {
if (event instanceof NavigationStart) {
this.loading = true;
} else if (event instanceof NavigationEnd) {
this.loading = false;
}
}
);
}
}
En el siguiente ejemplo, agregamos una latencia artificial de 500 ms para que puedas ver el ícono giratorio en acción.
Conclusión
Puedes reducir el tamaño del paquete de tus aplicaciones de Angular aplicando la división de código a nivel de ruta:
- Usa el generador de módulos de carga diferida de Angular CLI para crear el andamiaje automático en una ruta cargada de forma dinámica.
- Agrega un indicador de carga cuando el usuario navegue a una ruta diferida para mostrar que hay una acción en curso.