⚠️ This lesson is retired and might contain outdated information.

Lazy Load Angular Modules with the Router

John Lindquist
InstructorJohn Lindquist
Share this video with your friends

Social Share Links

Send Tweet
Published 8 years ago
Updated 8 months ago

Angular lazy loading is a core feature of Angular. Lazy loading allows your application to start up faster because it only needs to use the main App Module when the page initially loads. As you navigate between routes, it will load the additional modules as you define them in your routes. Make sure to properly organize your files into Angular’s module pattern so that files that belong to each module don’t get required by other modules.

[00:00] At this point, you probably think it's weird that my declarations inside of my app module, I need to declare the context and the home component. And then in my routes, I need to declare them as well. That seems like a lot of boilerplate and hard-coated dependencies between the router and components.

[00:15] What you can actually do about that is, in...I'll take my Home Directory. I'm going to create a Home Module. These modules are going to allow me to lazy load these packages or modules, or bundles of components and files, so we'll put another MG module here.

[00:33] This one will have imports of common module. Common module has NGF and all the common template things you'll use. It will have a declaration of home component. You remember how we just did that before in our app module. Then we can export default class home module.

[00:53] What we do in here is in our imports we use that same router module. This time instead of four roots we use four child. We'll configure the roots here, so roots. We say this time, the path. The root path of this module will load the component, home component. Drop these routes in here.

[01:15] Then in my app routes instead of saying component, I can say load children. And load children takes a string which will completely decouple these. The string will be app/home/home.module which is basically pointing to this app/home home.module.

[01:37] Finally in my app module I can get rid of this home component reference, get rid of the import. I'll hit Save, and now this will still load the home component. It's just that now we've decoupled this home and everything inside of it from the application.

[01:51] I can do the same thing in my contacts component. Let's extract those routes out just like we did before. We'll say home routes.ts. In my module I define my routes, so I'll paste those in here. I'll grab this router module 4 child, export that as the default. I'll make sure it'll import everything.

[02:13] Then in my home module I can get rid of that router module, just important home routes from home.routes. Now I'll drop my home routes in here. That was just for organization purposes, and everything will still work the same.

[02:28] Now, let's do that same thing for contacts, real fast. We'll say contacts module.ts. We'll create the empty module. We'll import the common module. We'll declare my contacts component, and export a default class of contacts module. We'll define our routes in a file. We'll say contacts.routes ts.

[02:54] This will be routes, which is an array. This one will have the path of at the root again, with a component of contacts component. Then we'll export a default router module for child. These routes. In my contacts module I can import the contacts routes from contacts routes, and drop them in my imports because this is a full module to import and load in.

[03:28] Finally, in my app routes I can say, load children app/contacts/contacts.module. This is still at the contacts path, that's fine. In my app module I can get rid of declaring the contacts component, remove the import.

[03:48] I'll hit Save, and now you'll see on the home component, and then it's /contacts. You'll see the load, this is a contacts component. We've decoupled these modules and inside the router we can remove these imports as well. Inside my route configuration for the app, you can see I'm loading in other modules.

[04:07] I'm lazy loading them in. This is doing this at run time, so that your final builds are as small as possible. Your code is split across these different modules. The angular compiler is set to split and organize these modules just as you would expect, so you don't have to worry about that too much.

[04:24] This load children that you see here is configured in whatever you're using for a loader. But basically, the angular CLI or angular2 starter, or the basic system JS build will all pre-configure this for you.

[04:35] Based on your custom settings, this path might change, so just check your loader and your build configuration on how that's set up. Again, you'll find no references to home or contacts inside of your app module, or app component. Everything is defined inside of app routes where it's just a string pointing to the module it's going to load.

[04:54] These modules are self-contained, and have their own route definitions based on the component it's going to use at this path. Similarly with contacts, we'll see the path is nothing but this is really app routes contacts and then nothing. That's how when we load contacts, it will still load in that module, and load in this contacts component.

Mac
Mac
~ 8 years ago

{path: '', loadChildren: 'app/home/home.module'}

When using webpack, this results in an error: module app/home/home.module not found. Anyone knows how to get this working with webpack?

Spencer
Spencer
~ 8 years ago

I'm also using webpack - and am getting a "Uncaught (in promise): ReferenceError: System is not defined" error with this configuration. It only started once I began refactoring using the Lazy Load method above.

I understand this tutorial is using System.js - does the loadChildren config require System.js ??

John Lindquist
John Lindquistinstructor
~ 8 years ago

System.js is not a requirement, just the default. Webpack loaders are available such as https://github.com/Quramy/angular2-load-children-loader

John Lindquist
John Lindquistinstructor
~ 8 years ago

I believe there's currently a bug/limitation around using default exports.

So you would target the @NgModule with loadChildren:'app/home/home.module#HomeModule' (where HomeModule is the exported class name of the module).

Noah Rawlins
Noah Rawlins
~ 8 years ago

I can't get this to work using webpack based v17 of the angular-cli and 2.1 of angular 2. It tells me it can't find the home module.

edit: i got it to work. apparently with cli version 17 you need to use relative paths. so './home/home.component#HomeComponent'

Jon
Jon
~ 8 years ago

Tried your solution and it still doesn't work for me using webpack (in the angular CLI).

Charles
Charles
~ 8 years ago

Same here, and solved here:

http://stackoverflow.com/questions/39493782/lazy-loading-in-angular2-rc7-and-angular-cli-webpack

Check my comment since i had a slighly different workaround.

qemweb
qemweb
~ 8 years ago

I almost tried everything and still the same issue: error_handler.js:50 EXCEPTION: Uncaught (in promise): Error: Cannot find module 'app/home/home.module' . you can see more details about my issue here : http://stackoverflow.com/questions/41396839/exception-uncaught-in-promise-error-cannot-find-module-app-home-home-modul

Please can someone help me !!

qemweb
qemweb
~ 8 years ago

it turns out that it's working on plunker but not on my machine !!!!!!! https://plnkr.co/edit/RjhjnWMBeC3xyPAPmh7c?p=preview someone to help please !!!

Osman
Osman
~ 8 years ago

I have the following error: ERROR in Cannot use "in" operator to search for providers. Whats the actual problem ? My settings. angular cli 1.0.0 node 6.10.2 os: win32 @angular 4.1.0 version.

Matt
Matt
~ 8 years ago

I am getting the same error as Osman, then I do a random save to rerun the server. Then I get this:

Unhandled Promise rejection: No provider for ApplicationRef! ; Zone: <root> ; Task: Promise.then ; Value:

CornerKitten
CornerKitten
~ 7 years ago

I had the same problem as Osman and Matt. After reading a suggestion from penleychan on GitHub, I made the following changes:

  • In app.routes.ts: Replace the export line with export const Routing = RouterModule.forRoot(routes);
  • In app.module.ts: Replace the routes import line with import { Routing } from './app.routes';
  • Also in app.module.ts: Update the NgModule decorator so that the imports array includes Routing (instead of routes as it previously was)

I’m not sure why Angular CLI works with the named constant export, instead of the default export. Seems like a bug. If anyone has ideas, I would love to learn more.

Jose
Jose
~ 7 years ago

Right answer is here: https://angular.io/docs/ts/latest/guide/ngmodule.html see the full example (final version)

Shyam
Shyam
~ 7 years ago

With Latest version its working fine after making 2 changes to code.

  1. remove default from export class ContactsModule{} // it is not able to understand default.
  2. in app.routes.ts add #HomeComponent at the end. {path: '', loadChildren: 'app/home/home.module#HomeModule'}
Markdown supported.
Become a member to join the discussionEnroll Today