angular-cli: [Bug] cli needs to be reloaded when a lazy loaded module is added in routes (FIXED)

Versions

Angular CLI: 1.7.1
Node: 8.9.4
OS: win32 x64
Angular: 5.2.6
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router

@angular/cli: 1.7.1
@angular-devkit/build-optimizer: 0.3.2
@angular-devkit/core: 0.3.2
@angular-devkit/schematics: 0.3.2
@ngtools/json-schema: 1.2.0
@ngtools/webpack: 1.10.1
@schematics/angular: 0.3.2
@schematics/package-update: 0.3.2
typescript: 2.5.3
webpack: 3.11.0

Repro steps

  • Run ng serve to start the application bundle
  • Create a new lazy module
  • Modify the routes in the main module to do lazy load of the new module

Observed behavior

The lazy module cannot be loaded.

Stack
null: ERROR
null: Error: Uncaught (in promise): TypeError: __webpack_require__.e is not a function
message: "Uncaught (in promise): TypeError: __webpack_require__.e is not a function
TypeError: __webpack_require__.e is not a function
    at webpackAsyncContext (eval at ./src/$$_lazy_route_resource lazy recursive (http://localhost:4200/main.bundle.js:13:1), <anonymous>:11:29)
    at SystemJsNgModuleLoader.loadAndCompile (webpack-internal:///./node_modules/@angular/core/esm5/core.js:6774:82)
    at SystemJsNgModuleLoader.load (webpack-internal:///./node_modules/@angular/core/esm5/core.js:6758:60)
    at RouterConfigLoader.loadModuleFactory (webpack-internal:///./node_modules/@angular/router/esm5/router.js:4626:122)
    at RouterConfigLoader.load (webpack-internal:///./node_modules/@angular/router/esm5/router.js:4606:52)
    at MergeMapSubscriber.eval [as project] (webpack-internal:///./node_modules/@angular/router/esm5/router.js:2098:115)
    at MergeMapSubscriber._tryNext (webpack-internal:///./node_modules/rxjs/_esm5/operators/mergeMap.js:133:27)
    at MergeMapSubscriber._next (webpack-internal:///./node_modules/rxjs/_esm5/operators/mergeMap.js:123:18)
    at MergeMapSubscriber.Subscriber.next (webpack-internal:///./node_modules/rxjs/_esm5/Subscriber.js:97:18)
    at ScalarObservable._subscribe (webpack-internal:///./node_modules/rxjs/_esm5/observable/ScalarObservable.js:53:24)"
promise: ZoneAwarePromise {__zone_symbol__state: 0, __zone_symbol__value: TypeError: __webpack_require__.e is not a function…}
rejection: TypeError: __webpack_require__.e is not a function
stack: "Error: Uncaught (in promise): TypeError: __webpack_require__.e is not a function
TypeError: __webpack_require__.e is not a function
    at webpackAsyncContext (eval at ./src/$$_lazy_route_resource lazy recursive (http://localhost:4200/main.bundle.js:13:1), <anonymous>:11:29)
    at SystemJsNgModuleLoader.loadAndCompile (webpack-internal:///./node_modules/@angular/core/esm5/core.js:6774:82)
    at SystemJsNgModuleLoader.load (webpack-internal:///./node_modules/@angular/core/esm5/core.js:6758:60)
    at RouterConfigLoader.loadModuleFactory (webpack-internal:///./node_modules/@angular/router/esm5/router.js:4626:122)
    at RouterConfigLoader.load (webpack-internal:///./node_modules/@angular/router/esm5/router.js:4606:52)
    at MergeMapSubscriber.eval [as project] (webpack-internal:///./node_modules/@angular/router/esm5/router.js:2098:115)
    at MergeMapSubscriber._tryNext (webpack-internal:///./node_modules/rxjs/_esm5/operators/mergeMap.js:133:27)
    at MergeMapSubscriber._next (webpack-internal:///./node_modules/rxjs/_esm5/operators/mergeMap.js:123:18)
    at MergeMapSubscriber.Subscriber.next (webpack-internal:///./node_modules/rxjs/_esm5/Subscriber.js:97:18)
    at ScalarObservable._subscribe (webpack-internal:///./node_modules/rxjs/_esm5/observable/ScalarObservable.js:53:24)
    at resolvePromise (webpack-internal:///./node_modules/zone.js/dist/zone.js:809:31)
    at resolvePromise (webpack-internal:///./node_modules/zone.js/dist/zone.js:775:17)
    at eval (webpack-internal:///./node_modules/zone.js/dist/zone.js:858:17)
    at ZoneDelegate.invokeTask (webpack-internal:///./node_modules/zone.js/dist/zone.js:421:31)
    at Object.onInvokeTask (webpack-internal:///./node_modules/@angular/core/esm5/core.js:4956:33)
    at ZoneDelegate.invokeTask (webpack-internal:///./node_modules/zone.js/dist/zone.js:420:36)
    at Zone.runTask (webpack-internal:///./node_modules/zone.js/dist/zone.js:188:47)
    at drainMicroTaskQueue (webpack-internal:///./node_modules/zone.js/dist/zone.js:595:35)
    at <anonymous>"
task: ZoneTask {_zone: Zone, runCount: 0, _zoneDelegates: null, …}
zone: Zone {_properties: Object, _parent: Zone, _name: "angular", …}
__proto__: Object {constructor: , name: "Error", message: "", …}

Desired behavior

The module should load without errors.

Mention any other details that might be useful (optional)

The real problem here, is that the cli does not catch up the module after the path is changed.

Current workarounds:

  • Just reloading the cli makes the lazy loaded module to work again.

I haven’t try every recommended workaround, but some of them are clearly not a option if you really want those modules to be lazy loaded. This is especially true for solutions like:

import { LazyModule } from 'lazy-module';

Anything that makes the module to be bundle with the app, is not an acceptable workaround.

If you are having issues with a lazy loaded module, that is NOT about changing the route o creating another lazy loaded module into the path when the CLI is serving, then you should look a proper issue, or create a new one.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 93
  • Comments: 128

Commits related to this issue

Most upvoted comments

I recomended change { path: 'user-panel', loadChildren: './user-panel/user-panel.module#UserPanelModule', },

to

{ path: 'user-panel', loadChildren: () => UserPanelModule, },

+1

Confirming that restarting ‘ng serve’ fixes the issue.

@michaeljota

  • Eager Loaded Routing Modules: The modules must be defined in the NgModule.imports before your router module.

  • Lazy Loaded Routing Modules: Remove the Lazy loaded modules from NgModule.imports

Either way, just make sure that your RoutingModule is last in the list of NgModule.imports E.g.: imports: [ BrowserModule, FormsModule, HeroesModule, AppRoutingModule ],

I had the same problem then stumbled across this article: https://angular.io/guide/router#module-import-order-matters.

Also look at the example (links at the top of the article) it shows different techniques to import Modules. E.g.: HerosModule is loaded eagerly CrisisCenterModule is loaded lazily

To solve the problem:

I upgraded @angular/cli to version 6.0.1 (not 100% sure if this made any difference) I moved the order of my imports around. (Move the *RoutingModule to the bottom of the list of imports) I also removed the lazy-loaded modules from the NgModule.imports property list Using an absolute path value for ‘loadChildren’ still works for me: loadChildren: ‘app/dashboard/dashboard.module#DashboardModule’

Same issue as 9488, see @kcir3v4M 's answer:

loadChildren’s value must be stored in an export const. Solves issues in both JIT and AOT and preserves lazy loading capabilities:

import { Routes } from ‘@angular/router’;

export const home = 'app/features/home/home.module#HomeModule';
export const user = 'app/features/user/user.module#UserModule';

export const routes: Routes = [
  {
    path: '',
    pathMatch: 'full',
    redirectTo: 'home'
  },
  {
    path: 'home',
    loadChildren: home
  },
  {
    path: 'user',
    loadChildren: user
  },
  {
    path: '**',
    redirectTo: 'home'
  }
];

@RafaelFronteira That worked for me what @sluglit suggested:

  1. Move the order of the imports. (Move the *RoutingModule to the bottom of the list of imports)
  2. Remove the lazy-loaded modules from the NgModule.imports property list

The second one solved the problem for me.

And leave the lazy loading as it was: loadChildren: ‘app/dashboard/dashboard.module#DashboardModule’

And don’t use AOT in dev build, it’s just a workaround, but not a solution.

+1; I fixed my issue with ng serve --aot

Update: This also happen when the lazy module throws an error in the first build.

@EcoFreak if you are using Lazy Loading you should never import the lazy module in your application, neither in AppModule, nor AppRoutingModule. You should only reference it by a string that points to the module class of that Lazy Module.

@michaeljota Even when downgrading the version, the problem remained in my case. The problem in my case was the order of imports of the main module. The AppRoutingModule defines the main routes and loads the remaining with loadChildren. The EquipmentsModule defined extra routes and it’s imported by AppRoutingModule. Before: (AppRoutingModule was imported before EquipmentsModule)

@NgModule({
  declarations: [
    AppComponent,
    LocationsComponent,
  ],
  imports: [
    HttpClientModule,
    BrowserModule,
    FormsModule,
    LayoutModule,
    AppRoutingModule,
    EquipmentsModule, //imported after
  ],

After: (AppRoutingModule was imported after EquipmentsModule)

@NgModule({
  declarations: [
    AppComponent,
    LocationsComponent,
  ],
  imports: [
    HttpClientModule,
    BrowserModule,
    FormsModule,
    LayoutModule,
    EquipmentsModule, //imported before
    AppRoutingModule,
  ],

Hope it helps!

Using full path: loadChildren: ‘app/registration/registration.module#RegistrationModule’

and ng serve --aot resolves this issue temporarily for me.

Same Problem with Angular 5.2.8 and CLI v1.7.3 Resolved that Issue by downgrading the CLI to v1.6.8. Alternate Workaround is using ng serve --aot suggested by @stanleyeosakul

@karol-depka, that’s not a solution, it’s just a work around. The only real solution is to reload the CLI.

You only can use the string version for AoT. So if you aren’t using AoT for anything, sure, you can do this. But, still, it is recommended to use the string version.

Czesc, @dkarski 😃.

Is this loadChildren: () => UserPanelModule gonna do proper lazy loading? If so, whey is the loadChildren: './user-panel/user-panel.module#UserPanelModule' so widespread (any advantages?)

Same problem here using Angular CLI 1.7.2.

I’m using ng serve --aot to fixes and now worked.

For me, that’s not working either (even after restarting the CLI). It’s just working if you use ng serve --aot, as said by @stanleyeosakul

For some reason, the string version stopped working for me even after reloading the CLI. This happened after I updated to @angular/cli@1.7.3 from v1.6.5…

After downgrading to v1.6.5, the strings are working fine again (still needs reloading)

@speti43

Remove the lazy-loaded modules from the NgModule.imports property list

This worked for me. loadChildren loads the module dynamically. No need to import the module in your app.module.

Cheers

Hey @dkarski, can you explain this solution? This worked for me, but I really did not understand how it works.

“{ path: ‘user-panel’, loadChildren: () => UserPanelModule, },”

I’m sorry if that’s a silly question …

+1

Either 1.7.3 + ng serve --aot or 1.6.8 + ng serve as temp fixes worked. I had to downgrade to 5.2.7 due to the issue 5.2.8 has with oidc-client.

updated to @angular/cli@1.7.3 and restart ng serve, it works.

I had this same issue but was not importing the lazy module in my app.module.ts nor did any of the other of the aforementioned suggested solutions resolve the error.

I was lazy loading a module that was using a custom angular component library. This library worked fine in ng5 but as soon as we upgraded to ng6, this error started occurring.

The fix was COMPLETELY unrelated to the error message, in fact, the error was terribly misleading and useless! We had to start stripping modules from our app ONE BY ONE to finally see what was causing the error to get some clue as to what the actual root cause was.

As it turns out in our custom library we were importing a few modules from an index.js (bucket) file which for whatever reason Angular compiler still can’t figure out.

// This is BAD!
import { MyModule } from '../my-modules/index';

// This is GOOD?
import { MyModule } from '../my-modules/my.module';

Sounds like my case is rare given that most people were able to resolve their issue with the solutions listed above but I wanted to comment in hopes that this could help someone else.

As of angular/cli 6.0.5 I face an issue where : Either I get a webpack.e is not a function Either I get ./xxx.module can not be found

@sluglit solution worked.

I was importing lazy loaded modules in my AppModule. Removing them made it OK 😃

Thanks buddy.

I was facing same issue. I am using latest version of Angular-CLI. I was facing issue because I forgot to add pathMatch: ‘full’ to my lazy loading module’s route.

Hello guys, managed to fix my problem. I was importing the ChildModule with the routes after the AppRoutingModule in AppModule. Just by swapping the order everything worked nicely.

Hope it helps 😉

@dkarski 's solution worked for me. Import your module import { Awesome } from './awesome/awesome.module'; and do loadChildren: () => Awesome

Restarting CLI solved issue

I’m runing @angular/cli v 1.7.3 and @Dercetech’s solution didn’t work. Any solutions?

For me I was making import module for my leazy loded module so that was wrong. I delete all this declarations but I had webpack error for my own created library something like webpack error e._ is not function ( I don’t remember the exactly the error). So i make ng --eject and all think work perfectly, but you must do npm run build to create production js code.

same issue here, even with using AoT

18:11:52.828 core.js:1448 ERROR Error: Uncaught (in promise): TypeError: undefined is not a function TypeError: undefined is not a function at Array.map (<anonymous>) at webpackAsyncContext (eval at ./src/$$_lazy_route_resource lazy recursive (main.bundle.js:20), <anonymous>:26:34) at SystemJsNgModuleLoader.loadFactory (core.js:6578) at SystemJsNgModuleLoader.load (core.js:6542) at RouterConfigLoader.loadModuleFactory (router.js:4543) at RouterConfigLoader.load (router.js:4523) at MergeMapSubscriber.eval [as project] (router.js:2015) at MergeMapSubscriber._tryNext (mergeMap.js:128) at MergeMapSubscriber._next (mergeMap.js:118) at MergeMapSubscriber.Subscriber.next (Subscriber.js:92) at Array.map (<anonymous>) at webpackAsyncContext (eval at ./src/$$_lazy_route_resource lazy recursive (main.bundle.js:20), <anonymous>:26:34) at SystemJsNgModuleLoader.loadFactory (core.js:6578) at SystemJsNgModuleLoader.load (core.js:6542) at RouterConfigLoader.loadModuleFactory (router.js:4543) at RouterConfigLoader.load (router.js:4523) at MergeMapSubscriber.eval [as project] (router.js:2015) at MergeMapSubscriber._tryNext (mergeMap.js:128) at MergeMapSubscriber._next (mergeMap.js:118) at MergeMapSubscriber.Subscriber.next (Subscriber.js:92) at resolvePromise (zone.js:809) at resolvePromise (zone.js:775) at eval (zone.js:858) at ZoneDelegate.invokeTask (zone.js:421) at Object.onInvokeTask (core.js:4740) at ZoneDelegate.invokeTask (zone.js:420) at Zone.runTask (zone.js:188) at drainMicroTaskQueue (zone.js:595)

@dkarski does that work with AoT?

Possible duplicate of #9488.

+1 same issue, restarting fixes it for me too