Join the Stack Overflow Community
Stack Overflow is a community of 4.7 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

Hi I'm trying to use angular-cli with webpack (+productivity) to build my angular2 app but I'm having issues when trying to lazy load modules which were working with version beta.10...

Project structure:

Project structure

package.json

{
  "name": "my-app",
  "version": "0.0.0",
  "license": "MIT",
  "angular-cli": {},
  "scripts": {
    "start": "ng serve",
    "lint": "tslint \"src/**/*.ts\"",
    "test": "ng test",
    "pree2e": "webdriver-manager update",
    "e2e": "protractor"
  },
 "private": true,
 "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.2",
    "angular2-cookie": "1.2.3",
    "core-js": "2.4.0",
    "material-design-icons": "2.2.3",
    "material-design-lite": "1.2.0",
    "reflect-metadata": "0.1.3",
    "rxjs": "5.0.0-beta.12",
    "ts-helpers": "^1.1.1",
    "zone.js": "0.6.21"
  },
  "devDependencies": {
    "@types/jasmine": "2.2.30",
    "@types/protractor": "1.5.16",
    "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": "0.13.22",
    "karma-chrome-launcher": "0.2.3",
    "karma-coverage": "1.0.0",
    "karma-jasmine": "0.3.8",
    "protractor": "3.3.0",
    "ts-node": "1.2.1",
    "tslint": "3.13.0",
    "typescript": "2.0.0"
  }
}

angular-cli.json

{
  "project": {
    "version": "1.0.0-beta.11-webpack",
    "name": "my-app"
  },
  "apps": [
    {
      "main": "main.ts",
      "test": "test.ts",
      "tsconfig": "tsconfig.json",
      "prefix": "app",
      "index": "index.html",
      "root": "src",
      "mobile": false,
      "scripts": [
        "polyfills.ts",
        "../node_modules/material-design-lite/material.min.js"
      ],
      "styles": [
        "../node_modules/material-design-icons/iconfont/material-icons.css",
        "../node_modules/material-design-lite/material.css"
      ],
      "assets": "assets",
      "environments": {
        "source": "environments/environment.ts",
        "dev": "environments/environment.ts",
        "prod": "environments/environment.prod.ts"
      }
    }
  ],
  "addons": [],
  "packages": [],
  "e2e": {
    "protractor": {
      "config": "config/protractor.conf.js"
    }
  },
  "test": {
    "karma": {
      "config": "config/karma.conf.js"
    }
  },
  "defaults": {
    "styleExt": "scss",
    "prefixInterfaces": false
  }
}

tsconfig.json

{
  "compilerOptions": {
    "declaration": false,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "lib": [
      "es6",
      "dom"
    ],
    "mapRoot": "./",
    "module": "es6",
    "moduleResolution": "node",
    "outDir": "../dist/out-tsc",
    "sourceMap": true,
    "target": "es5",
    "typeRoots": [
      "../node_modules/@types"
    ],
    "types": [
      "jasmine"
    ]
  }
}

app.routes.ts

import {Routes, RouterModule} from "@angular/router";
import {PageNotFoundComponent} from "./404.component";
import {AuthenticationGuard} from "./base/security";

const routes: Routes = [
  { path: '', redirectTo: 'home', pathMatch: 'full', canActivate: [AuthenticationGuard] },
  { path: 'home', loadChildren: 'app/modules/home/home.module#HomeModule' },
  { path: '**', component: PageNotFoundComponent }
];

export const routing = RouterModule.forRoot(routes, { useHash: true });

app.module.ts

import {NgModule} from "@angular/core";
import {BrowserModule} from "@angular/platform-browser";
import {routing} from "./app.routes";
import {AppComponent} from "./app.component";
import {PageNotFoundComponent} from "./404.component";
import {CoreModule} from "./core";

@NgModule({
  imports: [
    BrowserModule,
    routing,
    CoreModule
  ],
  declarations: [
    AppComponent,
    PageNotFoundComponent
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

modules/home/home.routes.ts

import {RouterModule} from '@angular/router';
import {HomeComponent} from './home.component';

import {AuthenticationGuard} from '../../base/security';

export const routing = RouterModule.forChild([
  { path: '', component: HomeComponent, canActivate: [AuthenticationGuard] }
]);

modules/home/home.module.ts

import {NgModule} from '@angular/core';
import {BaseModule} from '../../base/base.module';
import {routing} from './home.routes';
import {HomeComponent} from './home.component';
import {NavigationMenuComponent} from '../../base/components';

@NgModule({
    imports: [
    BaseModule,
    routing
  ],
  declarations: [
    HomeComponent,
    NavigationMenuComponent
  ],
  exports: [],
  providers: []
})
export class HomeModule {}

console error message: Console Error Message

Is there anything I'm forgetting here? I wasn't able to find any documentation anywhere on how to proceed with this... Thanks in advance!

share|improve this question
    
Project structure you provided doesn't contain folder home in folder app/modules, as a matter of fact, there's no file home.module at all, so when you go to route /home, there's no module to load: { path: 'home', loadChildren: 'app/modules/home/home.module#HomeModule' }. You can't load something that doesn't exist. (at least based on project structure picture you provided) – Stefan Svrkota Sep 14 at 13:59
    
Its not being displayed because the folder isn't opened, but its there. I will update the image – ImNotAnUser Sep 14 at 14:12
    
Have you tried { path: 'home', loadChildren: 'src/app/modules/home/home.module#HomeModule' }? (I added src to path) – Stefan Svrkota Sep 14 at 14:24
1  
I'm getting the same error and have posted the same question here: stackoverflow.com/q/39493782/616304 No replies yet but nice to know I'm not the only one getting this :-( – StephenWilson Sep 14 at 15:40

There's a loader for this (angular2-router-loader). However you can't use it with the CLI without hacking the config. Luckily, es6-promise-loader does work with the CLI out-of-the-box.

This is what worked out for me:

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

I have another solution :

on your app.routers.ts create a function like that :

let loadAoTModule = (path, module) => {

  let result = () => new Promise(function (resolve) {
    (require as any).ensure([], function (require: any) {
      resolve(require(path)[module]);
    });
  });

  return result;
}

const routes: Routes = [
  { path: '', redirectTo: 'customer', pathMatch: 'full'},

  { path          : 'customer'  ,
    // for a file locate on 'src/app/customer/customer.module'
    // and a module 'CustomerModule'
    loadChildren  :  loadAoTModule('./customer/customer.module', 'CustomerModule')

  }
];

work fine for me.

share|improve this answer

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.