Angular is een frontend JavaScript framework dat is ontwikkeld door Google voor het bouwen van schaalbare zakelijke webapplicaties. Sommige van deze applicaties kunnen behoorlijk groot worden, waardoor de laadtijd van je applicatie wordt beïnvloed.

Om de laadtijd te verkorten en de algehele ervaring van je gebruikers te verbeteren, kun je een techniek gebruiken die bekend staat als lazy loading. Met deze ingebouwde Angular feature kun je eerst alleen de benodigde onderdelen van de webapp laden, en daarna pas andere modules als dat nodig is.

In dit artikel leer je meer over lazy loading en hoe het je webapp kan helpen versnellen.

Wat is lazy loading?

Lazy loading verwijst naar de techniek om webpagina-elementen alleen te laden als ze nodig zijn. De tegenhanger is eager loading, waarbij alles onmiddellijk wordt geladen – of probeert te laden. Het eager loading van alle afbeeldingen, video’s, CSS en JavaScript code kan lange laadtijden betekenen – slecht nieuws voor gebruikers.

Lazy loading wordt vaak gebruikt voor afbeeldingen en video’s op sites met veel content. In plaats van alle media in één keer te laden, wat veel bandbreedte zou gebruiken en de pagina’s zou vertragen, worden die elementen pas geladen als hun plaats op de pagina in beeld komt.

Angular is een single-page framework dat voor veel van zijn functionaliteit afhankelijk is van JavaScript. De verzameling JavaScript van je app kan gemakkelijk groot worden naarmate de app groeit, en dat gaat gepaard met een overeenkomstige toename van het gegevensgebruik en de laadtijd. Om de zaken te versnellen kun je lazy loading gebruiken om eerst de vereiste modules op te halen en het laden van andere modules uit te stellen tot ze nodig zijn.

Voordelen van lazy loading in Angular

Lazy loading biedt voordelen die je site gebruiksvriendelijker maken. Dit zijn:

  • Snellere laadtijd: JavaScript bevat instructies voor het weergeven van je pagina en het laden van de gegevens ervan. Daarom is het een render-blocking resource. Dit betekent dat de browser moet wachten om alle JavaScript te laden voordat hij je pagina weergeeft. Bij lazy loading in Angular wordt de JavaScript opgesplitst in brokken die afzonderlijk worden geladen. Het eerste deel bevat alleen de logica die nodig is voor de hoofdmodule van de pagina. Hierbij wordt gebruik gemaakt van eager loading, waarna de overige modules gebruik maken van lazy loading. Door de omvang van het initiële deel te verkleinen, laat je de site sneller laden en renderen.
  • Minder datagebruik: Door de data op te delen in brokken en te laden als dat nodig is, gebruik je mogelijk minder bandbreedte.
  • Bespaarde browserresources: Omdat de browser alleen de benodigde delen laadt, verspilt hij geen geheugen en CPU aan het interpreteren en renderen van code die niet nodig is.

Lazy loading implementeren in Angular

Om deze tutorial te volgen heb je het volgende nodig:

  • NodeJS geïnstalleerd
  • Basiskennis van Angular

Je project opzetten

Je zult de Angular CLI gebruiken om je project te maken. Je kunt de CLI installeren met npm door het commando uit te voeren:

npm install -g @angular/cli

Maak daarna als volgt een project met de naam Lazy Loading Demo:

ng new lazy-loading-demo --routing

Dit commando creëert een nieuw Angular project, compleet met routing. Je werkt uitsluitend in de map src/app, die de code voor je app bevat. Deze map bevat je belangrijkste routingbestand, app-routing.module.ts. De structuur van de map moet er als volgt uitzien:

Screenshot: de Angular mapstructuur weergegeven in een terminal.
De mapstructuur van een Angular project.

Maak een featuremodule met Routes

Vervolgens maak je een featuremodule die lazy geladen wordt. Om deze module te maken voer je dit commando uit:

ng generate module blog --route blog --module app.module

Dit commando maakt een module genaamd BlogModule, samen met routing. Als je src/app/app-routing.module.ts opent, zie je dat het er nu zo uitziet:

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

const routes: Routes = [ { path: 'blog', loadChildren: () => import('./blog/blog.module').then(m => m.BlogModule) }];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { } 

Het deel dat belangrijk is voor lazy loading is de derde regel:

const routes: Routes = [ { path: 'blog', loadChildren: () => import('./blog/blog.module').then(m => m.BlogModule) }];

Die regel definieert de routes. De route voor de blog gebruikt het loadChildren argument in plaats van component. Het loadChildren argument vertelt Angular om de route lazy te laden – om de module alleen dynamisch te importeren als de route wordt bezocht, en dan terug te sturen naar de router. De module definieert zijn eigen childroutes, zoals blog/**, in zijn routing.module.ts bestand. De blogmodule die je hebt gegenereerd ziet er als volgt uit:

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { BlogComponent } from './blog.component';

const routes: Routes = [{ path: '', component: BlogComponent }];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class BlogRoutingModule { }

Je kunt zien dat dit routingsbestand een enkele route bevat, ''. Deze lost op voor /blog en wijst naar het BlogComponent. Je kunt meer componenten toevoegen en die routes in dit bestand definiëren.

Als je bijvoorbeeld een component wilt toevoegen die details over een bepaalde blogpost ophaalt, kun je die component met dit commando maken:

ng generate component blog/detail

Dat genereert de component voor de blogdetails en voegt hem toe aan de blogmodule. Om er een route voor toe te voegen, kun je die gewoon toevoegen aan je routes array:

const routes: Routes = [{ path: '', component: BlogComponent },
                        {path:"/:title",component: DetailComponent}];

Dit voegt een route toe die oplost voor blog/:title (bijvoorbeeld blog/angular-tutorial). Deze array van routes is lazy-loaded en niet opgenomen in de initiële bundel.

Lazy loading verifiëren

Je kunt eenvoudig controleren of lazy loading werkt door ng serve uit te voeren en de output te observeren. Onderaan je output zou je zoiets als dit moeten krijgen:

Screenshot: uitvoer van Angular's ng serve commando in de terminal.
Lazy loading verifiëren met Angular’s ng serve.

De uitvoer hierboven is verdeeld in twee delen: Initial Chunk Files zijn de bestanden die worden geladen als de pagina voor het eerst wordt geladen. Lazy Chunk Fileszijn lazy-loaded. De blogmodule staat in dit voorbeeld.

Controleren op lazy loading via de netwerklogs van de browser

Een andere manier om lazy loading te bevestigen is via het tabblad Network  in het paneel Developer Tools van je browser. (Op Windows is dat F12 in Chrome en Microsoft Edge, en Ctrl-Shift-I in Firefox. Op een Mac is dat CommandOptionI in Chrome, Firefox en Safari).

Selecteer het filter JS om alleen JavaScript bestanden te zien die via het netwerk zijn geladen. Na het eerste laden van de app zou je zoiets als dit moeten krijgen:

Screenshot: Angular JavaScript bestanden gelogd in Developer Tools.
Eerste log van JavaScript downloads bekeken in Developer Tools.

Als je navigeert naar /blog, zie je dat er een nieuw deaal, src_app_blog_blog_module_ts.js, is geladen. Dit betekent dat je module alleen werd opgevraagd toen je naar die route navigeerde, en dat hij lazy wordt geladen. Het netwerklog zou er ongeveer zo uit moeten zien:

Screenshot: bijgewerkte weergave van Angular JavaScript bestanden die zijn gelogd in Developer Tools.
Lazy geladen module verschijnt in downloads gelogd door Developer Tools.

 

Lazy loading versus eager loading

Laten we, ter vergelijking, ook een eager geladen module maken en zien hoe dat de bestandsgrootte en laadtijd beïnvloedt. Om dit te demonstreren maak je een module voor authenticatie. Zo’n module moet wellicht eager geladen worden, omdat authenticatie iets is dat je misschien van alle gebruikers verlangt.

Genereer een AuthModule door dit commando in de CLI uit te voeren:

ng generate module auth --routing --module app.module

Dit genereert de module en een routeringsbestand. Het voegt ook de module toe aan het bestand app.module.ts. In tegenstelling tot het commando dat we de vorige keer gebruikten om een module te genereren, voegt dit commando echter geen lazy-loaded route toe. Het gebruikt de --routing parameter in plaats van --route <name>. Dat voegt de authenticatiemodule toe aan de imports array in app.module.ts:

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    AuthModule //added auth module
  ],
  providers: [],
  bootstrap: [AppComponent]
})

Het toevoegen van AuthModule aan je AppModule imports array betekent dat de authenticatie module wordt toegevoegd aan het initiële deel bestanden en wordt opgenomen met de hoofd JavaScript bundel. Om dit te verifiëren kun je ng serve opnieuw uitvoeren en de uitvoer observeren:

Screenshot: Angular scripts nadat de authenticatiemodule is toegevoegd.
Uitvoer van Angular’s ng serve commando nadat authenticatiemodule is toegevoegd.

Zoals je ziet is de authenticatiemodule niet opgenomen als onderdeel van het lazy deel van de bestanden. Bovendien is de grootte van de initiële bundel toegenomen. Het bestand main.js is bijna verdubbeld in omvang en is toegenomen van 8 KB tot 15 KB. In dit voorbeeld is de toename klein, omdat de componenten niet veel code bevatten. Maar als je de componenten vult met logica, zal deze bestandsgrootte toenemen, wat een sterk argument is voor lazy loading.

Samenvatting

Je hebt geleerd hoe je lazy loading in Angular kunt gebruiken om modules alleen op te halen als ze nodig zijn. Lazy loading is een geweldige techniek om laadtijden te verbeteren, gegevensgebruik te verminderen, en je frontend en backend resources beter te benutten.

Lazy loading zal, samen met technologie als content distributie netwerken en het minifceren van JavaScript, zowel de prestaties van je website als de tevredenheid van je gebruikers verbeteren.

Als je een WordPress site ontwikkelt en je wilt de snelheid écht opvoeren, lees dan over Kinsta Edge Caching om een aantal indrukwekkende statistieken te zien.

Michael Nyamande

A digital product manager by day, Michael is a tech enthusiast who is always tinkering with different technologies. His interests include web and mobile frameworks, NoCode development, and blockchain development.