Apply Route-level Code Splitting and Lazy Loading with the Angular CLI

Share this video with your friends

Social Share Links

Send Tweet

When our Angular web app grows, the initial bundle size increases and so does the Time to Interactive. One of the countermeasures we can apply to improve that is to apply code-splitting to our app and consequently to lazy load those bundles only when they are needed. In this lesson we will learn how to apply route-level code splitting via the Angular CLI.

Article: https://web.dev/route-level-code-splitting-in-angular/

Instructor: [0:00] In modern routing applications, what we definitely want to do is to optimize the so-called "start-up time." Contrary to service-side router pages where the HTML is already ready, in modern applications, in single page applications, we first need to download the bunch of JavaScript that needs to be interpreted by the browser and then only we can start an app which renders the HTML.

[0:22] There's a metric that is called "Time to Interactive," and we definitely want to optimize for that. One comfortable matter we can apply here is to not always load the entire application to start-up. We have to reduce the number of files we have to actually download, and we just want to use the necessary ones to get our application up and running.

[0:41] For instance, right now if I go to that application and to the Language tab, then I filter here for JavaScript files. I do a reload, and we see the files get downloaded. If I click that button here, we get to new router for our application. If you take a look below here in the JavaScript section, nothing actually changes.

[0:59] The reason here is that the entire app gets already downloaded as startup. For the purposes of this exercise, let's try to lazy load this part. Whenever we switch to this Nyan route, we actually just want to download at that moment the necessary JavaScript files to run and visualize it.

[1:16] Let's go back here, and let's take a look at the structure of our application. If we take the full structure, we see that folder, Nyan. Actually, I want that these two here get bundled into its own JavaScript file.

[1:30] That is necessary, and this is a mechanism called code-splitting, such that later, at runtime, we have here a dedicated JavaScript file, just having these components here, and just get interpreted and loaded at that specific moment.

[1:45] How can we do that in Angular? In Angular, the Angular CLI already has a mechanism to create this on the fly. For instance, let's paste in this comment here. Here, we use the Ng command, which is the Angular CLI.

[1:58] We generate a new module, we give it a name, and we tell it, it should get hooked up to that app module. Then we also give it this route path. We want to generate here a route, and that will generate a lazy-loaded route that just gets loaded at the very specific moment when it is needed.

[2:15] Since we already have the entire code here, and we don't want to override everything, let's try to do this by hand to see the very steps that are involved here. First of all, what I need to do here is to create a new nyan.module.

[2:28] This is because, in Angular, the minimum unit that can be lazy loaded right now is a module. We need one of those. We have here an NgModule. I export class, and we just call it myModule.

[2:45] Now, we definitely have here a declaration section. We want that now, that Nyan component -- which right now, is registered here in the app module -- is now registered to that myModule. I would fetch in that one here.

[2:59] In the import section, we want to define here now a separate route. Right now, if I go to the app module, you can see here the route is defined inside here. We want to split that out into that myModule. Let's see how.

[3:13] First of all, I need to route a module. We use the forChild. Let's first import it here, because this is now a child route, and not in control of the entire application, but just a part of the entire routing system. The path here will be nothing. We will see why.

[3:31] We have path four, because it's an empty string. The component that you get loaded is obviously our Nyan component. All right, with that, we should be already set up in our Nyan module.

[3:41] Now, we need to do the lazy loading part. Let's go over to the app module. First of all, we need to remove that hard reference here, because we cannot directly import here a JavaScript file, because otherwise, that will get fetched into our main.js file.

[3:55] Actually, what we want is to have that in its dedicated own bundle. We cannot have any hard references, and so, let's remove here this Nyan component, which is registered, anyway, now in that Nyan module.

[4:07] Now, we need to change, obviously, this line here below. Since we don't have the component at-hand right now, but it will only be available at runtime later, we can use the loadChildren property here. Starting with Angular 8, this takes a function where we can directly use another import statement.

[4:23] I go here to that Nyan module, which we just created, because that's the part we have to lazy load. We cannot lazy load the component right now. Then we use here the callback, where we get here our Nyan module.

[4:39] Great. All right, so, let's save this here. Now, let's go here to our application. We can see here we have that main and files loaded. Now, when I right-click here that Nyan button, you can see here that another JavaScript file gets loaded in.

[4:53] The Angular CLI now has detected that we had here this loadChildren with that import statement. Automatically for that module, it generates a new, separate JavaScript bundle, which is a mechanism called code-splitting. It loaded it only when we actually navigate to that route.

[5:09] As you can see, again, if I refresh here, we just have, again, our main files. Once I click, this master files get loaded in on the fly over the network application, module gets booted, then we see the image just as before.