¿Para qué necesito Lazy Loading?
La mayoría de veces que creamos un proyecto en Angular (o al menos en mi caso) nos interesa que la aplicación cargue de una sola vez, de manera que sacrificando un pequeño período de tiempo al inicio, conseguimos que la velocidad y la fluidez sea mucho mas alta durante el resto de la navegación.
Para aplicaciones web usadas dentro de una red local, esta opción es más que perfecta, pero ¿qué podemos hacer si nuestra aplicación crece mucho y sobrecarga el navegador? ¿y si un tipo de usuario concreto sólo debe acceder a una parte muy pequeña de la aplicación?
Este problema lo solucionamos usando Lazy Loading, que básicamente significa que la aplicación web no se cargará de una sola vez al arranque, si no que se irá cargando a demanda según la necesidad del usuario.
Empezando: las rutas
Para empezar a trabajar con Lazy Loading lo primero es entender como carga las rutas Angular.
Si ya tenemos un proyecto, vamos a abrir nuestro fichero de rutas y si no es así puedes crear un nuevo proyecto especificando el parámetro –routing para que te genere automáticamente un fichero de rutas:
ng new --routing
En mi caso, mi fichero es el siguiente:
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { InicioComponent } from './inicio/inicio/inicio.component'; import { GalleryShowComponent } from './gallery-show/gallery-show/gallery-show.component'; import { AboutComponent } from './about/about/about.component'; import { GallerySelectorComponent } from './gallery-selector/gallery-selector/gallery-selector.component'; const routes: Routes = [ { path: 'informatica', loadChildren: './inicio/inicio.module#InicioModule' }, { path: 'gallery/view', loadChildren: './gallery-show/gallery-show.module#GalleryShowModule' }, { path: 'about', loadChildren: './about/about.module#AboutModule' }, { path: 'gallery', loadChildren: './gallery-selector/gallery-selector.module#GallerySelectorModule' }, { path: '**', redirectTo: '/informatica'} ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
Aquí lo que estamos viendo es que nuestro módulo de rutas define unas rutas concretas para las diferentes páginas que tendremos, pero en lugar de referenciar una ruta a un componente, lo estamos referenciando a un módulo. Vamos a fijarnos en la galaeria (por ejemplo):
{ path: 'gallery', loadChildren: './gallery-selector/gallery-selector.module#GallerySelectorModule' },
Tenemos por un lado el path, donde especificamos la url y en loadChildren escribiremos la ruta al archivo del módulo que contiene nuestros componentes para esa página. La sintaxis especifica después de la ruta el nombre del módulo (separado por una ‘#’.
LoadChildren lo que nos indica es que el módulo tendrá sus propias rutas definidas, por lo que no las cargamos, simplemente cuando las necesitemos ya las buscará.
Fíjate que cargamos ya los componentes que forman parte de los módulos que vamos a usar.
Hasta aquí fácil no?
Creando nuestros módulos
Ahora tendremos que definir nuestros módulos y escribir en ellos las rutas que cargaremos. Para seguir con el ejemplo, os pondré el contenido del módulo gallery-selector (es el que esta funcionando en esta misma web 😀 )
import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { GallerySelectorComponent } from './gallery-selector/gallery-selector.component'; import { Routes, RouterModule } from '@angular/router'; const routes: Routes = [ { path: '', component: GallerySelectorComponent}, ]; @NgModule({ imports: [ CommonModule, RouterModule.forChild(routes) ], declarations: [GallerySelectorComponent] }) export class GallerySelectorModule { }
En este fichero debemos fijarnos sobre todo en cuatro cosas:
- Importamos los componentes que vamos a usar y forman parte del módulo
- Definimos una variable routes con las rutas definitivas
- Importamos Routes y RouterModule
- Añadimos en imports «RouterModule.forChild(routes)» para que las rutas estén disponibles cuando el archivo de rutas maestro lo consulte.
Comandos útiles:
//Generar un módulo nuevo ng generate module mi-modulo //Cenerar un componente dentro de un módulo ng generate component mi-modulo/mi-componente
Probando la configuración
Llegados a este punto nuestra aplicación ya empezará a generar el Lazy loading, pero y si queremos comprobar que realmente funciona?
Sólo tenemos que usar las herramientas de desarrollador de Chrome y fijarnos en las Request que se generan:
Como puedes ver se genera una serie de peticione sque cargan los JS inciales y sólo al visitar un álbum se genera la petición de gallery-show.module.chunk.js
Esto mismo puedes comprobarlo en el apartado de galeria de la web y verlo por ti mismo! (Recuerda que una vez compilado angular renombra los módulos con un hash!)
Como curiosidad, comentar que como convenio se suele poner un + en cada carpeta que contiene un módulo cargado por Lazy Loading. De esta manera tendremos contentos hasta a los más puritanos!