Migliora le prestazioni della tua app utilizzando la suddivisione del codice a livello di percorso.
Questo post spiega come configurare la suddivisione del codice a livello di route in un'applicazione Angular, che può ridurre le dimensioni del bundle JavaScript e migliorare notevolmente il Time to Interactive.
Puoi trovare gli esempi di codice di questo articolo su GitHub. L'esempio di routing eager è disponibile nel ramo eager. L'esempio di suddivisione del codice a livello di route si trova nel ramo lento.
Perché è importante la suddivisione del codice
La complessità sempre crescente delle applicazioni web ha portato a un aumento significativo della quantità di JavaScript spedita agli utenti. I file JavaScript di grandi dimensioni possono ritardare notevolmente l'interattività, quindi possono essere una risorsa costosa, soprattutto sui dispositivi mobili.
Il modo più efficiente per ridurre i bundle JavaScript senza sacrificare le funzionalità delle applicazioni è introdurre una suddivisione del codice aggressiva.
La suddivisione del codice ti consente di dividere il codice JavaScript della tua applicazione in più blocchi associati a route o caratteristiche diverse. Questo approccio invia agli utenti il codice JavaScript di cui hanno bisogno solo durante il caricamento iniziale dell'applicazione, mantenendo bassi i tempi di caricamento.
Tecniche di suddivisione del codice
La suddivisione del codice può essere suddivisa in due livelli: a livello di componente e a livello di route.
- Nella suddivisione del codice a livello di componente, sposti i componenti nei propri blocchi JavaScript e li carichi lentamente quando sono necessari.
- Nella suddivisione del codice a livello di route, incapsula la funzionalità di ciascuna route in un blocco separato. Quando gli utenti esplorano la tua applicazione, recuperano i blocchi associati alle singole route e ottengono la funzionalità associata quando ne hanno bisogno.
Questo post è incentrato sulla configurazione della suddivisione a livello di percorso in Angular.
Applicazione di esempio
Prima di vedere come utilizzare la suddivisione del codice a livello di route in Angular, diamo un'occhiata a un'app di esempio:
Controlla l'implementazione dei moduli dell'app. All'interno di AppModule
sono definite due route: il percorso predefinito associato a HomeComponent
e un percorso nyan
associato a NyanComponent
:
@NgModule({
...
imports: [
BrowserModule,
RouterModule.forRoot([
{
path: '',
component: HomeComponent,
pathMatch: 'full'
},
{
path: 'nyan',
component: NyanComponent
}
])
],
...
})
export class AppModule {}
Suddivisione del codice a livello di route
Per configurare la suddivisione del codice, è necessario eseguire il refactoring della route eager nyan
.
La versione 8.1.0 dell'interfaccia a riga di comando Angular può fare tutto per te con questo comando:
ng g module nyan --module app --route nyan
Verrà generato:
- Un nuovo modulo di routing chiamato NyanModule
- Una route in AppModule
chiamata nyan
che caricherà dinamicamente l'elemento NyanModule
- Una route predefinita in NyanModule
- Un componente chiamato NyanComponent
che verrà eseguito quando l'utente seleziona la route predefinita.
Esaminiamo questi passaggi manualmente per capire meglio come implementare la suddivisione del codice con Angular.
Quando l'utente accede al percorso nyan
, il router mostrerà NyanComponent
nella presa del router.
Per utilizzare la suddivisione del codice a livello di route in Angular, imposta la proprietà loadChildren
della dichiarazione di route e combinala con un'importazione dinamica:
{
path: 'nyan',
loadChildren: () => import('./nyan/nyan.module').then(m => m.NyanModule)
}
Ci sono due differenze principali rispetto al metodo "eager":
- Hai impostato
loadChildren
anzichécomponent
. Quando si utilizza la suddivisione del codice a livello di route, è necessario puntare ai moduli caricati dinamicamente, anziché ai componenti. - In
loadChildren
, una volta risolta la promessa, restituisciNyanModule
anziché indirizzare aNyanComponent
.
Lo snippet riportato sopra specifica che, quando l'utente accede a nyan
, Angular deve caricare dinamicamente nyan.module
dalla directory nyan
e visualizzare il componente associato alla route predefinita dichiarata nel modulo.
Puoi associare la route predefinita a un componente utilizzando questa dichiarazione:
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 {}
Questo codice mostra NyanComponent
quando l'utente accede a https://example.com/nyan
.
Per verificare che il router Angular scarichi lentamente nyan.module
nel tuo ambiente locale:
- Premi "Ctrl+Maiusc+J" (o "Comando+Opzione+J" su Mac) per aprire DevTools.
Fai clic sulla scheda Rete.
Fai clic su NYAN nell'app di esempio.
Tieni presente che il file
nyan-nyan-module.js
viene visualizzato nella scheda Rete.
Trova questo esempio su GitHub.
Mostra una rotellina
In questo momento, quando l'utente fa clic sul pulsante NYAN, l'applicazione non indica che sta caricando JavaScript in background. Per dare all'utente un feedback durante il caricamento dello script, ti consigliamo di aggiungere una rotellina.
Per farlo, inizia aggiungendo il markup per l'indicatore all'interno dell'elemento router-outlet
in app.component.html
:
<router-outlet>
<span class="loader" *ngIf="loading"></span>
</router-outlet>
Poi aggiungi una classe AppComponent
per gestire gli eventi di routing. Questo corso imposterà il flag loading
su true
quando sente l'evento RouteConfigLoadStart
e il flag su false
quando sente l'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;
}
}
);
}
}
Nell'esempio che segue abbiamo introdotto una latenza artificiale di 500 ms per consentirti di vedere la rotellina in azione.
Conclusione
Puoi ridurre la dimensione del bundle delle applicazioni Angular applicando la suddivisione del codice a livello di route:
- Usa il generatore di moduli con caricamento lento dell'interfaccia a riga di comando Angular per lo scaffold automatico di una route caricata dinamicamente.
- Quando l'utente sceglie un percorso lento, aggiungi un indicatore di caricamento per mostrare che è in corso un'azione.