Angular-cli: webpack rc5 loadChildren -Error: Uncaught (in promise): TypeError: Cannot read property 'import' of undefined

Created on 11 Aug 2016  Â·  19Comments  Â·  Source: angular/angular-cli

  • when i click the link redirecting to the lazy load path, error occurs:

browser_adapter.js:84 Error: Uncaught (in promise): TypeError: Cannot read property 'import' of undefined
at resolvePromise (zone.js:538)
at zone.js:515
at ZoneDelegate.invoke (zone.js:323)
at Object.onInvoke (ng_zone_impl.js:53)
at ZoneDelegate.invoke (zone.js:322)
at Zone.run (zone.js:216)
at zone.js:571
at ZoneDelegate.invokeTask (zone.js:356)
at Object.onInvokeTask (ng_zone_impl.js:44)
at ZoneDelegate.invokeTask (zone.js:355)

  • my source code is:

export const routes: Routes = [
{ path: '', redirectTo: 'contact', pathMatch: 'full'},
{ path: 'crisis', loadChildren: 'app/crisis/crisis.module' },
{ path: 'heroes', loadChildren: 'app/hero/hero.module' }
];
which is from
https://angular.io/docs/ts/latest/guide/ngmodule.html

**everything is ok in systemjs**
  • my environment is:
    angular-cli: 1.0.0-beta.11-webpack.2

angular: 2.0.0-rc.5


Thanks!

1 (urgent) bufix

Most helpful comment

i'm trying with angular-cli from master npm linked, i'm getting the System is not defined error and adding Systemjs typings does not help (there are typings for System in src/typings.d.ts apparently), investigating... i would really like to have the lazy loading working with webpack

All 19 comments

I think you should use a custom module loader, not just a string.
See closed issue: https://github.com/angular/angular/issues/9938

Just updated my starter project for webpack.
I used Brandon's approach to lazy load Task2:

export const routes: Routes = [
    { path: '', redirectTo: 'task1', pathMatch: 'full' },
    { path: 'task1', component: Task1Component },
    {
        path: 'task2',
        loadChildren: load(() => new Promise(resolve => {
            (require as any).ensure([], (require: any) => {
                resolve(require('./task-2/task2.module').Task2Module);
            })
        }))
    }
];

Anyway, I would be grateful for any easier solution.
CC: @brandonroberts

to @iurii-kyrylenko ,

@TheLarkInn can you add some context to the current resolution of this issue?

I need the loadChildren feature with webpack and can't wait until RC6 is released therefore I used the nightly builds but it does not work :(

ReferenceError: System is not defined

So I realized that I now need systemjs (in other words... 2 module loaders?)?

Which steps are needed to make the Angular 2 webpack example (https://angular.io/docs/ts/latest/guide/webpack.html) work with loadChildren?

Thank you so much!

I think the best way to describe the status of this is simply that the CLI team hasn't gotten to it yet. Most likely, if things go well, down the road a bit you will simply use ng new, ng generate route, etc., and it will all get wired up to "just work" the first time. I can't speak to the timeline of that, I'm not on the CLI team.

I believe there are some lazy loading examples around the web right now, although I don't have a URL handy as I type this. As far as I know, these examples don't yet use CLI.

this is actually not closed... #1632 only adds the base for lazy loading, the actual loader seems to be missing... or atleast I didn't manage to find it in the commits :)

The built in loader assumes you have SystemJS available globally already. You need to add SystemJS to your head scripts, and be on the master builds of angular also for this to work. If you want to do it the "webpack" way right now you'll need a custom loader.

@brandonroberts thanks for the explaination, i couldn't gather that from the code. I guess I'll have to wait for the official 'webpack' wait to land.

When I do that (what a mess, 2 module loaders...), it tries to load the module file by using baseURL + string from the router (e.g. http://localhost:8080/app/configuration/configuration.module). This makes no sense to me (e.g. bundling your applicationn or without bundling you must configure the server to find the file at this location and you run into trouble with route URL naming conflicts). The official Angular 2 documentation says, it does not matter if you use SystemJS or Webpack... The official Angular 2 ngmodule documentation says you must use loadChildren when dealing with modules and routes (this only works with SystemJS therefore modules only work with SystemJS in RC5). I know that I can use synchronous routes in RC6 which work with Webpack (this works, I tested it with the nightly builds).

@Martin-Wegner if you're concerned with the implementation, wait until its officially supported and explained by the CLI. Once RC6 lands, using loadChildren with a function that returns a promise will be supported.

I imagine that the CLI will replace the loadChildren string with the appropriate function returning a promise that resolves the lazy loaded module as if you did it the "webpack way" and will not being using the provided SystemJS loader.

@Martin-Wegner If you want to use the angular-cli current in npm with webpack([email protected]) and make this work right now you have to do the following steps:

1) add the file async-ng-module-loader.ts to the root of your folder.
2) add these 2 lines to app.module.ts:
import {NgModule, NgModuleFactoryLoader} from '@angular/core';
import {AsyncNgModuleLoader} from './async-ng-module-loader';
3) at the provider to app.module.ts
providers: [
{provide: NgModuleFactoryLoader, useClass: AsyncNgModuleLoader}
],
4) at this import to app.routing.ts
import {load} from './async-ng-module-loader';
5) at this path to the module to be lazy loaded,in this example heroes to the HeroModule
{
path: 'heroes',
loadChildren: load(() => new Promise(resolve => {
(require as any).ensure([], require => {
resolve(require('./hero/hero.module').HeroModule);
});
}))
}
6) verify your HeroModule if its export with default or not.
If it's with default (export default class HeroModule {}) then remove the default word or change the path in step 5 to
{
path: 'heroes',
loadChildren: load(() => new Promise(resolve => {
(require as any).ensure([], require => {
resolve(require('./hero/hero.module').default);
});
}))
}

@stefanaerts thank you :) I hope there will be a out of the box solution like the async routing described here: https://angular.io/docs/ts/latest/guide/ngmodule.html#!#lazy-load

Well that document is based on a angular version that uses SystemJs module
loader.
So the docs are not up to date, or the angular CLI is ahead of the docs.
The source code example with it in plunkr uses also a systemjs config file.
But if you create a project with 'ng new' using the angular cli you get the
main.ts platformBrowserDynamic().bootstrapModule(AppModule);

So soon it will be all synchronised(the docs i mean) to handle asynchronous
stuff.
Nice ha all synchronised -> to handle asynchronous stuff (-)

Kind Rg,
Stefan.

On Mon, Aug 29, 2016 at 4:27 PM, Martin-Wegner [email protected]
wrote:

@stefanaerts https://github.com/stefanaerts thank you :) I hope there
will be a out of the box solution like the async routing described here:
https://angular.io/docs/ts/latest/guide/ngmodule.html#!#lazy-load

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/angular/angular-cli/issues/1636#issuecomment-243140116,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ADg4935WwhcMefXrvh0sbdx3klFkB4Xuks5qkuxogaJpZM4JhzxM
.

@Martin-Wegner I'm guessing if you add typings for System.import it will work? The PR referenced (https://github.com/angular/angular-cli/pull/1632) uses the webpack contextplugin so the existing System.imports should work for webpack as well? At least i think that's the idea.
check this for typescript support: https://github.com/TypeStrong/ts-loader/issues/129
I'm just theorizing after reading up on webpack contextplugin, i will test it when i have time :p
edit: System.import only works with webpack 2.x as far as i know

i'm trying with angular-cli from master npm linked, i'm getting the System is not defined error and adding Systemjs typings does not help (there are typings for System in src/typings.d.ts apparently), investigating... i would really like to have the lazy loading working with webpack

Getting the same error myself. Uncaught (in promise): ReferenceError: System is not defined. I'm using Angular2 RC6 with Angular-CLI 1.0.0-beta.11-webpack.2

Is there any glimmer of hope here?

@stephenwilson1984 you can install System using npm install systemjs --save and add it to your scripts array in the angular-cli.json

From there you can use loadChildren with a function that returns a System.import with the path to your lazy loaded module.

I have an example repo here using the CLI and RC6: https://github.com/brandonroberts/router-cli-aot

To everyone here (before I lock this conversation):

This feature is working

You DO NOT need SystemJS in your code. You need RC6 (the latest router specifically) because webpack relies on SystemJS.import() calls which it wouldn't see if you didn't have the latest.

Again, DO NOT install SystemJS. You're in a world of pain if you do while using webpack (it's possible to make it work but it's not worth it).

What the #1632 PR did was to pass modules from lazy loading to webpack so webpack would split the bundles in chunks. Then webpack will read angular's code and see System.import() and update it to call the proper chunks.

The new issue is due to https://github.com/angular/angular/pull/11049 changing the way System is called making it impossible for webpack to detect. We're working on a fix.

The Angular-CLI itself is working fine. The bug is in Angular's code. We might be able to fix in Angular-CLI by making a custom plugin.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

rajjejosefsson picture rajjejosefsson  Â·  3Comments

jbeckton picture jbeckton  Â·  3Comments

donaldallen picture donaldallen  Â·  3Comments

hareeshav picture hareeshav  Â·  3Comments

gotschmarcel picture gotschmarcel  Â·  3Comments