I have created a new app using ng new but when I try to configure a module to load using lazy loading I keep getting an error that the module cannot be found.

EXCEPTION: Uncaught (in promise): Error: Cannot find module 'app/home/home.module'

package.json

"dependencies": {
    "@angular/common": "2.0.0-rc.7",
    "@angular/compiler": "2.0.0-rc.7",
    "@angular/core": "2.0.0-rc.7",
    "@angular/forms": "2.0.0-rc.7",
    "@angular/http": "2.0.0-rc.7",
    "@angular/platform-browser": "2.0.0-rc.7",
    "@angular/platform-browser-dynamic": "2.0.0-rc.7",
    "@angular/router": "3.0.0-rc.3",
    "core-js": "^2.4.1",
    "rxjs": "5.0.0-beta.12",
    "ts-helpers": "^1.1.1",
    "zone.js": "^0.6.21"
  },
  "devDependencies": {
    "@types/jasmine": "^2.2.30",
    "angular-cli": "1.0.0-beta.11-webpack.9-4",
    "codelyzer": "~0.0.26",
    "jasmine-core": "2.4.1",
    "jasmine-spec-reporter": "2.5.0",
    "karma": "1.2.0",
    "karma-chrome-launcher": "^2.0.0",
    "karma-cli": "^1.0.1",
    "karma-jasmine": "^1.0.2",
    "karma-remap-istanbul": "^0.2.1",
    "protractor": "4.0.5",
    "ts-node": "1.2.1",
    "tslint": "3.13.0",
    "typescript": "2.0.2"
  }
  • angular2 RC7
  • angular-cli: 1.0.0-beta.11-webpack.9-4
  • node: 6.5.0
  • os: win32 x64

app.routing.ts:

import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

const appRoutes: Routes = [{
    path: '',
    redirectTo: 'home',
    pathMatch: 'full'
},
{
    path: `home`,
    loadChildren: `app/home/home.module`
}];
export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes);

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';

import { AppComponent } from './app.component';

import { routing } from './app.routing';

@NgModule({
  declarations: [
     AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule,
    routing
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.css']
})
export class AppComponent {
  title = 'app works!';
}

app.component.html

<router-outlet></router-outlet>

I'm sure I'm missing something stupid but I tried various options and nothing has worked so far. Given my configuration, am I missing anything?

Thanks in advance, Stephen

share|improve this question
up vote 3 down vote accepted

With RC7, you can do as follow:

const appRoutes: Routes = [
  {
    path: 'home',
    loadChildren: 'app/home/home.module#HomeModule',
  }
];

Don't forget the "#"

Then kill ng serve and restart it

It will works with angular-cli@webpack

P.S: The angular convention is to prefix lazy loaded folders with a (+) e.g. +home/

share|improve this answer
1  
Thanks, this solved it for me. Killing ng serve and restarting it is crucial for it to work. It'll give errors about not finding the module until you restart ng serve. – Yarrgh Sep 15 at 18:01
    
i had same problem. I also had a relative path in value for loadChildren (coming from Angular2 SystemJs configuration). I got it working using Khosro's approach AND making the path 'app/home/home.module#HomeModule' instead of './home/home.module#HomeModule' – Tom Schreck Sep 19 at 20:11

The problem is not present in RC7 anymore.

{path:"lazy", loadChildren: 'app/path/to/module#Class'}

will work.


The mechanism you are using is still systemjs based. I couldn't make it work with webpack using the "path#class" syntax. So we require the module directly:

First we'll need the es6-promise-loader:

npm i --save-dev es6-promise-loader

Then define your route like this:

{path:"lazy", loadChildren: () => require('es6-promise!./path/to/module')('ClassName')}

the es6-promise-loader replaces the above with this:

loadChildren: () => new Promise(function (resolve) {
        require.ensure([], function (require) {
          resolve(require('./path/to/module')['ClassName']));
        });
      });

which is the proper way to load a module with webpack, but cumbersome to put into every route.

share|improve this answer
1  
Is this the recommended approach from the Angular team? I can't find any docs that support this... – Askanison4 Sep 15 at 8:19
    
I couldn't find any docs that would reveal the secret of lazy-loading with webpack. If you look at the stack trace, the "path#class" lazy-loading mechanism is clearly designed for SystemJS. This is the only working approach I know. – j2L4e Sep 15 at 8:26
    
"path#class" isn't in the trace although I have tried this as well. Not sure where the issue lies though, is it Angular RC7 (Doubtful) or Angular-Cli or Webpack? – StephenWilson Sep 15 at 8:48
    
There's a loader for webpack (github.com/brandonroberts/angular2-router-loader), but you won't be able to use it with angular-cli without hacking the config. es6-promise-loader works with the CLI out-of-the-box. – j2L4e Sep 15 at 8:49
    
check this stack-trace i.stack.imgur.com/u0s8z.png for over here stackoverflow.com/questions/39492299/…. It's using SystemJsNgModule-loader which doesn't seem to fit our needs. – j2L4e Sep 15 at 8:52

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.