Search code examples
angularangular2-routingangular-cli

angular-cli router lazy loading


I am attempting to run a sample web app to learn how lazy loading with Angular modules works. I generated the app via angular-cli 1.0.0-beta.24 which uses angular 2.4.1. I generated the core app and then 3 components. I then added routing at the app level and directly reference the first two components by importing the components into the app module. For the third component I simply added the routing using the loadChildren method specified in the Angular routing docs. My routing configuration for the main app is as follows:

const appRoutes: Routes  = [
    { path: 'comp1', component: Comp1Component},
    { path: 'comp2', component: Comp2Component},
    { path: 'comp3', loadChildren: 'app/comp3/comp3.module'}
];

export default RouterModule.forRoot(appRoutes);

I turned the code for the third component into a module and removed all imports from the app to the third component. The routing config for the the module is as follows:

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

export default RouterModule.forChild(routes);

When I run the app, the routes for Comp1 and Comp2 work fine, when I click the link for Comp3 (the module route), I get the following error logged to the console:

EXCEPTION: Uncaught (in promise): Error: Cannot find module ./comp3/comp3.module'.
Error: Cannot find module './comp3/comp3.module'.
    at webpackEmptyContext (http://localhost:4200/main.bundle.js:77:8) [angular]

It seems that webpack is not handling the lazy loading. I've tried all kinds of path variants of the "loadChildren" call including:

loadChildren: 'app/comp3/comp3.module#Comp3Module'

with no change in behavior (still get the error above). New to angular2 so may be something in my code, but I see others getting the same error. My google/stackoverflow foo has not lead me to a solution. I added my sample app to my Github account here.

I saw this issue logged by another developer with the Angular team but they kicked it as a support issue to StackOverflow because the sample worked on plunkr. I'm sure there is a clue somewhere in there, but I don't really know enough about webpack and what it is doing to find the differences in the plunkr vs. ng serve run of the app.

Adding additional info. The app's html template looks like this (also available on github repo):

 <h1>
    {{title}}
 </h1>
 <ul>
    <li><a class="nav-link" routerLink="/comp1" routerLinkActive="active">Component 1</a></li>
    <li><a class="nav-link" routerLink="/comp2" routerLinkActive="active">Component 2</a></li>
    <li><a class="nav-link" routerLink="/comp3" routerLinkActive="active">Component 3</a></li>
  </ul>
  <p></p>
  <router-outlet></router-outlet>

I copied my source tree for this app (from src/app on down) to the angular2 seed project, and with some minor expected tweeks, it runs fine there and continues to fail in the environment set up by angular-cli. The only change I made to my TS source is to use the relative pathing:

{ path: 'comp3', loadChildren: './comp3/comp3.module#Comp3Module'}

for the loadChildren call. I changed my Github example code to reflect this update, but it still fails under the angular-cli environment.


Solution

  • Change your comp3.routes.ts:

    export default RouterModule.forChild(routes);
    

    To:

    export const comp3Routing = RouterModule.forChild(routes);
    

    On your comp3.module.ts replace:

    import comp3Routes from "./comp3.routes";
    

    To:

    import { comp3Routing } from "./comp3.routes";
    

    Lastly import comp3Routing, so it should look like this:

    @NgModule({
        imports: [
            CommonModule,
            RouterModule,
            comp3Routing,
        ],
        declarations: [
            Comp3Component
        ],
        exports: [
            Comp3Component
        ],
    
        providers: [],
    })
    export class Comp3Module { }
    

    And your lazy loading for comp3 should work.