7

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

Stephen Wilson
  • 1,484
  • 1
  • 15
  • 30

2 Answers2

7

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/

Khosro
  • 116
  • 6
  • 3
    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 '16 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 '16 at 20:11
  • It worked for me but, in my case, I had to make the path './home/home.module#HomeModule'); exporting the module with 'export class HomeModule { }' rather than 'export default class HomeModule { }'. – Carlos Araya Nov 14 '16 at 12:53
  • This also worked for me, but I had to do ```rm -rf /node_modules /tmp``` and then run ```npm install```. It was the only way. – Oriana Ruiz Jan 12 '17 at 04:33
0

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.

j2L4e
  • 6,914
  • 34
  • 40
  • 2
    Is this the recommended approach from the Angular team? I can't find any docs that support this... – aaron-bond Sep 15 '16 at 08: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 '16 at 08:26
  • 1
    "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? – Stephen Wilson Sep 15 '16 at 08:48
  • There's a loader for webpack (https://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 '16 at 08:49
  • check this stack-trace http://i.stack.imgur.com/u0s8z.png for over here http://stackoverflow.com/questions/39492299/error-when-trying-to-lazy-load-feature-modules-using-angular-cli-with-webpack/39496473#39496473. It's using `SystemJsNgModule-loader` which doesn't seem to fit our needs. – j2L4e Sep 15 '16 at 08:52
  • Also, what those loaders do is basically replacing the `path#Class` syntax with a function that's similar to what I posted in my answer. Sorry for the spam. – j2L4e Sep 15 '16 at 08:59
  • @j2L4e Re. angular2-router-loader Vs angular-cli, as of now it seems that it also supports AOT: see [Loader options (AoT compilation)](https://github.com/brandonroberts/angular-router-loader/blob/master/docs/options.md#loader-options-aot-compilation) – superjos Jan 05 '17 at 12:27