Migliora le prestazioni della tua app utilizzando la suddivisione del codice a livello di route.
Questo post spiega come configurare la suddivisione del codice a livello di route in un'applicazione Angular, in modo da ridurre le dimensioni del bundle JavaScript e migliorare notevolmente il tempo di risposta.
Puoi trovare i codici di esempio di questo articolo su GitHub. L'esempio di routing eager è disponibile nel branch eager. L'esempio di suddivisione del codice a livello di route si trova nel ramo lazy.
Perché la suddivisione del codice è importante
La complessità sempre crescente delle applicazioni web ha portato a un aumento significativo della quantità di JavaScript inviata agli utenti. I file JavaScript di grandi dimensioni possono ritardare notevolmente l'interattività, quindi possono essere una risorsa dispendiosa, soprattutto sui dispositivi mobili.
Il modo più efficiente per ridurre i bundle JavaScript senza sacrificare le funzionalità nelle tue applicazioni è introdurre una suddivisione del codice aggressiva.
La suddivisione del codice ti consente di suddividere il codice JavaScript della tua applicazione in più blocchi associati a route o funzionalità diverse. Questo approccio invia agli utenti solo il codice JavaScript di cui hanno bisogno durante il caricamento iniziale dell'applicazione, mantenendo bassi i tempi di caricamento.
Tecniche di suddivisione del codice
La suddivisione del codice può essere eseguita a due livelli: a livello di componente e a livello di route.
- Nella suddivisione del codice a livello di componente, sposti i componenti nei rispettivi chunk JavaScript e li carichi in modo lazy quando sono necessari.
- Nella suddivisione del codice a livello di percorso, la funzionalità di ogni percorso viene incapsulata in un blocco separato. Quando gli utenti navigano nella tua applicazione, recuperano i chunk associati ai singoli percorsi e ottengono la funzionalità associata quando ne hanno bisogno.
Questo post si concentra sulla configurazione della suddivisione a livello di route in Angular.
Applicazione di esempio
Prima di approfondire 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 definiti due percorsi: 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 del percorso 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
Verranno generati:
- Un nuovo modulo di routing denominato NyanModule
- Un percorso in AppModule
denominato nyan
che caricherà dinamicamente NyanModule
- Un percorso predefinito in NyanModule
- Un componente denominato NyanComponent
che verrà visualizzato quando l'utente raggiunge il percorso predefinito
Eseguiamo manualmente questi passaggi per comprendere meglio l'implementazione della suddivisione del codice con Angular.
Quando l'utente accede al percorso nyan
, il router mostrerà NyanComponent
nell'uscita del router.
Per utilizzare la suddivisione del codice a livello di route in Angular, imposta la proprietà loadChildren
della dichiarazione della route e combinala con un'importazione dinamica:
{
path: 'nyan',
loadChildren: () => import('./nyan/nyan.module').then(m => m.NyanModule)
}
Esistono due differenze principali rispetto al percorso eager:
- Hai impostato
loadChildren
anzichécomponent
. Quando utilizzi la suddivisione del codice a livello di route, devi fare riferimento ai moduli caricati dinamicamente anziché ai componenti. - In
loadChildren
, una volta risolta la promessa, restituisciNyanModule
anziché fare riferimento 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 nyan.module
in modo lazy nel tuo ambiente locale:
- Premi "Control+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 della rete.
Trova questo esempio su GitHub.
Mostrare un selettore circolare
Al momento, quando l'utente fa clic sul pulsante NYAN, l'applicazione non indica che sta caricando JavaScript in background. Per fornire un feedback all'utente durante il caricamento dello script, ti consigliamo di aggiungere un'animazione di attesa.
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>
Aggiungi poi una classe AppComponent
per gestire gli eventi di routing. Questa classe imposta il flag loading
su true
quando rileva l'evento RouteConfigLoadStart
e imposta il flag su false
quando rileva 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 seguente abbiamo introdotto una latenza artificiale di 500 ms per consentirti di vedere l'indicatore in azione.
Conclusione
Puoi ridurre le dimensioni del bundle delle tue applicazioni Angular applicando la suddivisione del codice a livello di route:
- Utilizza il generatore di moduli con caricamento differito di Angular CLI per creare automaticamente lo schema di un percorso caricato dinamicamente.
- Aggiungi un indicatore di caricamento quando l'utente passa a un percorso lazy per indicare che è in corso un'azione.