Lazy loading Angular Modules

Angular provides an efficient, elegant and easy way to manage module loading at runtime as soon as the user requests certain features of our application. Other than being ‘feature fancy’, its a way to reduce our application bundle via outsourcing application features that are not required at startup time.

Tell me more…

Thanks to @angular/router package, implementing this in our applications is easier than you might think. So let’s get started.

1. Creating our million dollar fancy application

We’re going to use Angular CLI to create our application, let’s create a new app.

For those who are getting started, this command will create an angular application and its basic structure, followed by the dependency installation. For more please refer to @angular/cli.

Notice I passed the routing flag to our ng new command, this will generate the routing for our application.

2. Creating our main components

Let’s suppose we’re going to have two main components in our app, the former is going to be the HomeComponent where our users will visit our application when they hit let’s say fancy-app.fancydomain.

The latter, our BigFeatureComponent that’s gonna be the one we will Lazy Load as the user navigates through our application. So let’s create them using angular CLI.

For the purpose of this tutorial, we are skipping the creation of test files passing the spec=false flag. Do not forget to add tests to your production ready applications.

This way angular CLI will automagically create our two new components and updates our AppModule for us with its respective declarations. More info about @angular/cli commands can be found here

For now our project structure should look like this.

3. Adding features to our Application

For now, we have all our application structure generated. Now is time to start adding those game-changing features.

First we’re going to create the routing for our application, which will be in charge of mocking up the navigation of our application as the users perform application tasks. Open up our app-routing.module.ts and complete it up with the following routes.

For a more detailed information about how the @angular/router package works, here’s the official documentation.

By adding this, our angular app will register the path routes /home and /bigComponent and make them available to the user, as they use our app show them the appropriate content, HomeComponent and BigFeatureComponent respectively.

Each of the components will have its own game changer feature, but for the purpose of this blog post I’ll keep things simple and will focus in what really matters, how to Lazy load an angular Module. More on that later.

I added each of the respectively anchor tags to our HomeComponent and BigFeatureComponent HTML’s, to be able to navigate through our application components.

Our home-component.component.html should look like this.

And our big-feature.component.html like this.

And to make sure we’ve been following around our app.module.ts should look like this so far, with the respective component declarations and the routes registered as imports.

4. Running our App

ng serve

Now if we fire up our application, we should see this screens.

Navigating through our app.
Nothing fancy to see here…

Right now, our application bootstraps all the needed resources at boot time. Each component defined previously, is bundled in the initial package that our apps serves to the client requesting our application.

We can see this in our browser’s devtools network tab, as soon as we start our application all the bundled resources of our application are downloaded and while the user navigates through it everything is available as the application were downloaded at the startup time.

Application served at startup time, with all the assets needed to work as a single page application

5. Adding module lazy loading

So far so good. Now we want to lazy load our components as soon as the user requests certain feature of our application. First, we should create a new Module, which is necessary to wrap up the components that are going to be lazy load.

The following @angular/cli command will create our new module, called big-module.

Second, we need to adjust the folder structure to reflect the wrapping of BigFeatureComponent into our new recently created Module BigModule. So far our application folder structure should look like this, with our big-module folder wrapping big-feature-component.

Now, the interesting part about this blog post. We need to register our new Module to be lazy loaded as the user request certain feature of our app. Let’s say, when the user navigates to /bigComponent route.

For this we are gonna make use of the LoadChildren Module available in the @angular/router package. Registering a route with LoadChildren is as easy as the following code snippet. Here we just changed, which component we’re going to load for the children module we want to lazy load.

Loading a children component using LoadChildren Module
The LoadChildren path should be composed by the relative path of the module without its extension + # sign + module exported class.

In our case ‘./big-module/big-module.module#BigModuleModule’ follows the latter pattern. Being BigModuleModule the exported class of our big-module module.

Next, we need to define the child routes of our now lazy loaded module. As we just gonna have /bigComponent route and not any child route after it, we just need to register the empty path as child route for our lazy loaded module followed by the component we want to load after the mentioned route is reached in our router configuration.

One interesting thing to notice here, its the use of RouterModule.forChild method. This is used because we are in a child module, being AppModule the root module of our application and is where we registered our top level application routes.

Only call RouterModule.forRoot in the root AppRoutingModule (or the AppModule if that's where you register top level application routes). In any other module, you must call the RouterModule.forChild method to register additional routes.

So far so good, we’ve been through a long road. That’s all we need to get our BigModule lazy loaded as we navigate to /bigComponent route.

big-module.module.chunk.js downloaded as we navigate /bigComponent route path.

We can see in the network tab of the browser’s developer tools that our app as soon as we hit the route path, a new chunk of the application is downloaded. That’s the module being Lazy Loaded.

Yes, we did it !

That’s all folks, hope you have enjoyed this post and have learned how to lazy load a module in angular. Go further, and try to optimize your application using this strategy aiming to reduce the inicial bundle size and speeding application boot time.

Full source code can be found in github here.
Be sure to follow me @CamiloGiraldo and hope to share more blog post with you guys in the future. Feel free to share. Thank you.