Separar la aplicación en módulos
June 22, 2019 · View on GitHub
ng g m Admin --routing
installing module
create src/app/admin/admin-routing.module.ts
create src/app/admin/admin.module.ts
En admin.module.ts
@NgModule({
declarations: [
AdminListComponent,
AdminEditComponent,
AdminAddComponent
],
imports: [
CommonModule,
AdminRoutingModule
],
exports:[
AdminHomeComponent
]
declarations: []
})
export class AdminModule { }
Hace falta CommonModule, pero no BrowserModule. BrowserModule solamente es necesario en el raíz
En admin-routing.module.ts
const routes: Routes = [
{path: '', component: AdminHomeComponent},
{path: 'users/list', component: UsersListComponent},
{path: 'users/edit/:id', component: UsersEditComponent},
{path: 'users/new', component: UsersAddComponent},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule]
})
export class AdminRoutingModule { }
Y en nuestro módulo raíz
@NgModule({
imports: [
...
AdminModule
...
],
})
export class AppModule { }
Y en el routing padre
{
path: 'admin',
loadChildren: 'app/admin/admin.module#AdminModule' // Antes de Angular 8
loadChildren: () => import('app/admin/admin.module').then(mod => mod.AdminModule) }, // A partir de Angular 8
},
Por ejemplo, en app.component.html añadimos un enlace al componente exportado (AdminHomeComponent)
<li><a class="nav-link" routerLink="/admin" routerLinkActive="active">Admin Home</a></li>
Nota: Angular-cli integra por defecto los componentes las directivas y las pipes que genera en app.module.ts. Si queremos que estén integrados en otro módulo distinto, debemos ejecutar el comando de la siguiente manera:
ng g component nombre-modulo/nombre-componente
o bien
ng g component nombre-componente --module=nombre-modulo
Lazy loading
Lazy loading bajo demanda:
Para activar lazy loading en un path necesitamos:
- Cargar un módulo en el path del routing padre
- Definir una ruta por defecto en el módulo hijo
- Configurar el routerModule del módulo lazy con .forChild()
- NO incluir el módulo lazy en el módulo raíz
Lazy loading con preloading
La librería de routing ofrece dos estrategias de preloading:
- No preloading (por defecto). Los módulos se cargan bajo demanda.
- Preloading de TODOS los módulos.
Vamos a crear unos cuantos módulos y componentes
ng g m lazy1
ng g m lazy2
ng g m lazy3
ng g m lazy4
ng g m lazy5
ng g c lazy1 --module=lazy1
ng g c lazy2 --module=lazy2
ng g c lazy3 --module=lazy3
ng g c lazy4 --module=lazy4
ng g c lazy5 --module=lazy5
Y a configurar el routing
{ path: 'admin', loadChildren: 'app/admin/admin.module#AdminModule'},
{ path: 'lazy1', loadChildren: 'app/lazy1/lazy1.module#Lazy1Module'},
{ path: 'lazy2', loadChildren: 'app/lazy2/lazy2.module#Lazy2Module'},
{ path: 'lazy3', loadChildren: 'app/lazy3/lazy3.module#Lazy3Module'},
{ path: 'lazy4', loadChildren: 'app/lazy4/lazy4.module#Lazy4Module'},
{ path: 'lazy5', loadChildren: 'app/lazy5/lazy5.module#Lazy5Module'},
(A paritr de Anguar 8)
{ path: 'admin', loadChildren: () => import('app/admin/admin.module').then(mod => mod.AdminModule) },
{ path: 'lazy1', loadChildren: () => import('app/lazy1/lazy1.module').then(mod => mod.Lazy1Module) },
{ path: 'lazy2', loadChildren: () => import('app/lazy2/lazy2.module').then(mod => mod.Lazy2Module) },
{ path: 'lazy3', loadChildren: () => import('app/lazy3/lazy3.module').then(mod => mod.Lazy3Module) },
{ path: 'lazy4', loadChildren: () => import('app/lazy4/lazy4.module').then(mod => mod.Lazy4Module) },
{ path: 'lazy5', loadChildren: () => import('app/lazy5/lazy5.module').then(mod => mod.Lazy5Module) },
Para activar el preloading basta configurar el método .forRoot() con la propiedad preloadingStrategy:
RouterModule.forRoot(
appRoutes,
{
enableTracing: true, // <-- debugging purposes only
preloadingStrategy: PreloadAllModules
}
)
Si recargamos la aplicación, veremos cómo empiezan a descargarse los módulos de forma lazy justo inmediatamente después de que el componente actual haya sido renderizado completamente en la pantalla.
Ejercicio: Crear un guard de tipo canLoad que impida cargar uno de los módulos lazy
Custom preloading
También es posible también programar estrategias de preloading personalizadas.
Para este ejemplo, vamos a poner una propiedad preload en el data de las rutas de un par de módulos:
{ path: 'admin', loadChildren: 'app/admin/admin.module#AdminModule', data: { preload: true } },
{ path: 'lazy1', loadChildren: 'app/lazy1/lazy1.module#Lazy1Module'},
{ path: 'lazy2', loadChildren: 'app/lazy2/lazy2.module#Lazy2Module'},
{ path: 'lazy3', loadChildren: 'app/lazy3/lazy3.module#Lazy3Module'},
{ path: 'lazy4', loadChildren: 'app/lazy4/lazy4.module#Lazy4Module', data: { preload: true } },
{ path: 'lazy5', loadChildren: 'app/lazy5/lazy5.module#Lazy5Module'},
Y vamos a crear un servicio que implemente un preloading selectivo:
ng g s selective-preloading-strategy --module=app-routing
Debemos implementar el interfaz PreloadingStrategy, que nos obliga a implementar la función preload().
import 'rxjs/add/observable/of';
import { Injectable } from '@angular/core';
import { PreloadingStrategy, Route } from '@angular/router';
import { Observable } from 'rxjs/Observable';
@Injectable({
providedIn: 'root',
})
export class SelectivePreloadingStrategy implements PreloadingStrategy {
preload(route: Route, load: () => Observable<any>): Observable<any> {
if (route.data && route.data['preload']) {
console.log('Preloaded: ' + route.path);
return load();
} else {
return Observable.of(null);
}
}
}
En este ejemplo, solo se cargarán los módulos que tengan una propiedad preload con valor true.
Ahora cambiamos el preloadingStrategy del módulo de routing por el nuestro.
@NgModule({
imports: [RouterModule.forRoot(appRoutes,{
enableTracing: false,
preloadingStrategy: SelectivePreloadingStrategy
})],
exports: [RouterModule],
providers: []
})
export class AppRoutingModule { }
https://angular.io/guide/router#preloading-background-loading-of-feature-areas