These days mobile applications can become quite big. A dashboard consisting of 10 components here, another page with 2-6 components there and of course some services providing data for all the separate components.
Each of those components also consists of an HTML page, a stylesheet and the actual logic in a TypeScript file. All of this code is automatically bundled by Webpack, which makes deploying a lot easier. But it also has a downside, the browser needs to download these files when loading the page and it can only start loading your web application when the entire bundle has been downloaded.
Angular and Webpack already offer some nifty out-of-the-box features that help you minimize the size of your bundles, such as code minification,
(which is automatically activated in dev mode when running Angular 9 or above, to improve the developer experience).
But there are still a few more steps you can take to manually improve the performance of your application. One of these features is offered by the Angular Router, called “Lazy loading.”
CREATING OUR DEMO APPLICATION
Now that we know the theory behind lazy loading we can look at an actual use case. Let’s rebuild our disco application, but this time we are going to build it using just Angular.
First, we need to create a new project
Now that we have created our project we can start programming.
ADDING LAZY LOADING
Adding lazy loading to our application is fairly straightforward. All we need to do is change the way we define our routes. But before we can add routes we need a new page to redirect to. So let’s create one (you can add as many colors as you want):
In order to make it a real disco app we need to add some color. So replace the styles array in yellow.component.ts with the following:
Now that we’ve created our (yellow) color page we can add it to our routing file. Open the src/app/app-routing.module.ts and replace the routes with the following:
This will load our yellow page on startup. The .then(m => m.YellowModule) will load the actual Module that is connected to the page. This will, however, load just the Module and not the components that are related to that Module. Because of that we need to add a router path to the Module definition, which tells the router to also load the component when the Module is loaded.
Let’s add this path to the Module, go to src/app/yellow/yellow.module.ts and add the following code:
Now that we have defined the route we need to register it as a child route with the router. We can achieve this by calling the RouterModule.forChild method. Add the following code to the imports array of the YellowModule:
And that’s it! If we now fire up our application via
ng serve you can see that the yellow page has been loaded. You can optionally replace the contents of the
app.component.ts with the following
template to make it clearer:
VIEWING THE RESULT
So the page now loads and everything looks okay, but how can we check whether the lazy loading has an actual effect on the build output? Just run ng build and look at the /dist folder. You will find a separate module file for the yellow Module in there:
A separate file means a separate download.
PRELOADING ALL THE MODULES
Lazy loading already improves the performance of the application by splitting up the bundle into multiple smaller bundles. But there is still a catch. The application will still download every resource on app load, even the bundles that are not yet needed. Which still means that we need to wait until everything has finished downloading before we can load the application.
For this the Angular Router has a second trick up its sleeve. We can change this behavior by setting the preloadingStrategy of the Angular Router to PreloadAllModules. This allows the router to delay the download of bundles which aren’t directly required to a period of inactivity after the initial application load. With this, fewer resources have to be loaded upfront, which results in shorter loading times of your application.
Changing the loading strategy is even easier than implementing lazy loading, because it only requires an additional configuration object for the router.
Add the following code to src/app/app-routing.module.ts:
and change the RouterModule import to:
That’s it! That is all we need to make it work. If we now look at the network tab in our browser (don’t forget to run
ng serve), we can see that the
yellow-yellow-module.js bundle is loaded after the initial load!
Thanks to the following Rockstars for proofreading and editing this article: Vincent Spaa, Erik Euser, Ivar Lugtenburg, Robin Gordijn.