Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
jjlgjkkl opened this issue Aug 11, 2016 · 19 comments · Fixed by #1632
Labels
P1 Impacts a large percentage of users; if a workaround exists it is partial or overly painful type: bug/fix

Comments

@jjlgjkkl
Copy link

jjlgjkkl commented Aug 11, 2016

  • 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!

@iurii-kyrylenko
Copy link

iurii-kyrylenko commented Aug 11, 2016

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

@iurii-kyrylenko
Copy link

iurii-kyrylenko commented Aug 11, 2016

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

@jjlgjkkl
Copy link
Author

to @iurii-kyrylenko ,

@filipesilva
Copy link
Contributor

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

@Martin-Luft
Copy link

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!

@kylecordes
Copy link

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.

@reflog
Copy link

reflog commented Aug 23, 2016

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 :)

@brandonroberts
Copy link
Contributor

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.

@reflog
Copy link

reflog commented Aug 23, 2016

@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.

@Martin-Luft
Copy link

Martin-Luft commented Aug 23, 2016

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).

@brandonroberts
Copy link
Contributor

@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.

@stefanaerts
Copy link

@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);
    });
    }))
    }

@Martin-Luft
Copy link

@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

@stefanaerts
Copy link

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
#1636 (comment),
or mute the thread
https://github.com/notifications/unsubscribe-auth/ADg4935WwhcMefXrvh0sbdx3klFkB4Xuks5qkuxogaJpZM4JhzxM
.

@mjolk
Copy link

mjolk commented Aug 31, 2016

@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

@mjolk
Copy link

mjolk commented Sep 5, 2016

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

@stephenwilson1984
Copy link

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?

@brandonroberts
Copy link
Contributor

@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

@hansl
Copy link
Contributor

hansl commented Sep 5, 2016

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 angular/angular#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.

@angular angular locked and limited conversation to collaborators Sep 5, 2016
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
P1 Impacts a large percentage of users; if a workaround exists it is partial or overly painful type: bug/fix
Projects
None yet
Development

Successfully merging a pull request may close this issue.