angular-cli: lazy loading not working in Angular 6

I’m getting this error when try to navigate to ‘http://localhost:4200/dashboard’ lazy loading route in angualr, angualr-cli 6.0.0

ERROR Error: Uncaught (in promise): Error: Cannot find module “app/dashboard/dashboard.module”. Error: Cannot find module “app/dashboard/dashboard.module”. at $_lazy_route_resource lazy namespace object:5

const routes: Routes = [
    {
        path: 'login',
        loadChildren: 'app/login/login.module#LoginModule',

    },
    {
        path: '',
        component: MasterComponent,
        children: [
            {
                path: 'dashboard',
                loadChildren: 'app/dashboard/dashboard.module#DashboardModule'
            }
        ],
    },
    {
        path: '**',
        redirectTo: 'login
    }
];


@NgModule({
    imports: [RouterModule.forRoot(routes)],
    exports: [RouterModule],
    providers: []
})
export class AppRoutingModule {
}

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 44 (3 by maintainers)

Most upvoted comments

this will work ‘./login/login.module#LoginModule’ ‘./dashboard/dashboard.module#DashboardModule’

Edited, thanks to @filipesilva 👏

Efectively, there are three posible solutions:

a) Using relative path loadChildren: './... b) Using absolute path starting with loadChildren: 'src/app/... c) tsconfig.app.json --> BaseUrl: "./"

The issue

Actually, the problem comes from typescript config. Before NG 6, the scaffold generated by CLI set the BaseUrl in tsconfig.app.json which is located inside /src. Currently, it is set by tsconfig.json located outside /src, but continues pointing to ./. Because of this, loadChildren path to module should be relative or include src folder.

Angular CLI: 6.0.3
Node: 8.11.1
OS: darwin x64
Angular: 6.0.2

Remove the lazy loading module in app.module. It will work.

What about relative parent? ‘…/’ is not working anymore 😦

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'

had the same issue, and @sluglit had the solution with “Move the *RoutingModule to the bottom of the list of imports” ! Nothing related to the 2 other bullet points, at least on my side.

@bigbharatjain - I had a very similar issue, my problem was because I forgot to remove the Import of my lazy module from my “AppComponent” I had: image

And changed it to

image

I had to remove “StockListModule” from the imports array in app.module.ts

Why does this seems to change very often?

I mean, one day the relative path method seems to work, and then the next day with the newly create project, it doesn’t works anymore and I have to resort to the absolute path method instead.

What is going on here?

I’m getting a similar error after upgrading from Angular 5 to 6:

Router Event: NavigationError platform-browser.js:211 NavigationError(id: 4, url: ‘/ping’, error: TypeError: undefined is not a function) ERROR Error: Uncaught (in promise): TypeError: undefined is not a function TypeError: undefined is not a function

Utilizing this syntax has worked for me locally

Before (didn’t work): { path: 'bing', loadChildren: './bing/bing.module#BingModule' }

After (does work): { path: 'bing', loadChildren: () => BingModule}

Though when I upload to Heroku I am getting the error again (I am using Express for deployment). The strange part is the old syntax works with Express… what is going on?!

Angular CLI: 6.1.5 Angular: 6.1.6 Node: 8.11.4

@Steveiwonder Thanks a lot. Your solution worked for me.

Running ng serve with HMR I have observed the following: The initial compile will not build the chunk for the lazy loaded module and compilation fails with the reported error “cannot find module”. If I modify anything which forces a HMR recompile, the chunk for the lazy loaded route is created and the route now works correctly.

@Ricard you are right that the documentation on Angular.io shows a non-relative path. I am discussing this with the docs folks. Parts of the docs are not yet aligned with Angular CLI and I suspect this is one of them.

@filipesilva I saw your commit https://github.com/angular/devkit/commit/33af719bad1d34cca814f59ab3c0796204af9c39 The property has moved from tsconfig.app.json to src/tsconfig.json file, but not it’s value ./, therefore newly generated v6 apps by CLI wont be able to find lazy load modules with paths defined as lazy load documentation.

I suggest this change. It preserves baseUrl: "./" on tsconfig.json and each project have its tsconfig.app.json that overwrites baseUrl property. I hope this is aligned with the multiprojects approach and tooling.

If you prefere to use relative url for loadChildren, It should be updated on documentation and tutorial.

@Ricard also opened an issue about this in https://github.com/angular/devkit/issues/969, and it includes a simple repro that I will use for my response https://github.com/Ricard/ng6-lazyload-issue-evidence.

There’s a couple parts to this issue. Yes it is all about baseUrl as that is how non-relative paths in typescript are resolved from. In Angular CLI 6 projects the baseUrl is ./, whereas in Angular CLI 1.x it was ./src/.

But we also never recommended using imports like loadChildren: 'app/mod/mod.module#ModModule'. The recommended approach is to always use a relative path, such as loadChildren: './mod/mod.module#ModModule'.

We did change the baseUrl for new projects in Angular CLI 6, and this was done purposefully. Angular CLI 6 supports multiple projects and it does not make a lot of sense to use src/ as baseUrl in that case.

If you have multiple projects and each of them has their own baseUrl, you’re going to need a very specific file setup for that to work for both builds and for your editor. This is not trivial.

You can try to change the baseUrl for your workspace if you’re sure you’re never going to have other projects though. But as a default we try to be safe for multiple types of usage.

@Ricard Thanks you!! I solved the issue with your solution.

I have faced a similar problem twice so far and have ended here both times. So I’m just gonna leave this here for the next time I stumble upon the same problem. I had a problem where the lazy loaded module was not found, but sometimes after changing any of the files which triggered rebuild, it started working. The problem was an unexported function inside app.module which was actually not used anywhere else (once it was a urlmatcher, and the other time a factory function used in a provider). Both times were solved by adding export before the function declaration.

I wasted way too much time on this only to realize that since I’m using Webpack without the Angular CLI I had to add angular-router-loader to the configuration for it to work and generate the chunks.

https://www.npmjs.com/package/angular-router-loader

Hoping someone else that comes around here, or those that have resorted to using => may find this useful.

I have solve the issue by updating angular cli and other packages to latest version by checking it through ng udpate command

Name Version Command to update -------------------------------------------------------------------------------- @angular/cli 6.0.8 -> 6.1.5 ng update @angular/cli @angular/core 6.1.0 -> 6.1.4 ng update @angular/core @angular/material 6.4.2 -> 6.4.6 ng update @angular/material

I had a very similar issue and work by adding src

{
    path: 'heroes',
    loadChildren: 'src/app/heroes/heroes.module#HeroesModule'
  }

Not sure if this will help anyone but what I’ve noticed on my specific project was that if I add a space in my route, it seems to compile without issues.

app.routing.module

const routes: Routes = [
    {
        path: '',
        children: [
            {
                path: ' ', loadChildren: './app/main/main.module#MainModule'
            }
        ]
    },
];

However, if the path is ‘’ it will have trouble finding MainModule.

I am having the similar issue, I have followed all the comments mentioned in this issue. But still it doesn’t work for me. I have followed steps given at https://update.angular.io/ After upgrading to Angular 6, application shows blank white screen for all the routes. And also there is no error shown in browser console. Each route redirects to default path http://localhost:4200. But http://localhost:4200/admin is working fine. I have asked question here.

In previous versions loadChildren path support with ‘app/path/to/module#Module’ but it’s not working anymore, instead of that use relative path ‘./path/to/module#Module’

angular/aio/content/examples/lazy-loading-ngmodules example also has been changed 3 days ago with Angular 6 release

https://github.com/angular/angular/commit/f44a2c730a84cd86695d1851395ad28423704bd0

Angular community has been responding to the issue which I raised, Please find the responses below.

https://github.com/angular/angular-cli/issues/10673#issuecomment-391786453

According to responses of angular community they will update document.

usage need to change from

const routes: Routes = [
  {
    path: 'customers',
    loadChildren: 'app/customers/customers.module#CustomersModule'
  },
  {
    path: 'orders',
    loadChildren: 'app/orders/orders.module#OrdersModule'
  },
  {
    path: '',
    redirectTo: '',
    pathMatch: 'full'
  }
];

to

const routes: Routes = [
  {
    path: 'customers',
    loadChildren: './customers/customers.module#CustomersModule'
  },
  {
    path: 'orders',
    loadChildren: './orders/orders.module#OrdersModule'
  },
  {
    path: '',
    redirectTo: '',
    pathMatch: 'full'
  }
];

One other tip:

Module import order matters https://angular.io/guide/router#module-import-order-matters

@dalu - thanks for tip. it worked for me