Skip to content

lazy loading not working in Angular 6 #10673

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

Closed
cagline opened this issue May 6, 2018 · 44 comments
Closed

lazy loading not working in Angular 6 #10673

cagline opened this issue May 6, 2018 · 44 comments

Comments

@cagline
Copy link

cagline commented May 6, 2018

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 {
}
@Patrick-Kan
Copy link

this will work
'./login/login.module#LoginModule'
'./dashboard/dashboard.module#DashboardModule'

@alexzuza
Copy link

alexzuza commented May 6, 2018

angular/angular@f44a2c7

@mkollers
Copy link

mkollers commented May 7, 2018

What about relative parent? '../' is not working anymore :(

@sluglit
Copy link

sluglit commented May 11, 2018

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'

@tjaussoin-luna
Copy link

tjaussoin-luna commented May 16, 2018

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.

@Ricard
Copy link

Ricard commented May 23, 2018

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

@grapgrap
Copy link

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

@filipesilva
Copy link
Contributor

@Ricard also opened an issue about this in angular/devkit#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
Copy link

Ricard commented May 24, 2018

@filipesilva I saw your commit angular/devkit@33af719
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.

@filipesilva
Copy link
Contributor

@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
Copy link
Contributor

Opened as angular/angular#24109

@tomschreck
Copy link

@dalu - thanks for tip. it worked for me

@cagline
Copy link
Author

cagline commented May 28, 2018

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

angular/angular@f44a2c7

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

#10673 (comment)

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

@Vips120
Copy link

Vips120 commented May 31, 2018

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

@bigbharatjain
Copy link

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.

@Steveiwonder
Copy link

Steveiwonder commented Jun 11, 2018

@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

@ahmetbasaran
Copy link

ahmetbasaran commented Jun 12, 2018

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.

@DerejeKitaw
Copy link

DerejeKitaw commented Jun 27, 2018

I had a very similar issue and work by adding src....

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

@thanapongp
Copy link

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?

@mccainz
Copy link

mccainz commented Aug 9, 2018

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.

@vivekreddy
Copy link

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

@Vino16491
Copy link

Vino16491 commented Aug 24, 2018

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

@phutaneVinayak
Copy link

Hi folks
I try following it working.
{
path: 'customers',
loadChildren: 'src/app/customers/customers.module#CustomersModule'
},
{
path: 'orders',
loadChildren: 'src/app/orders/orders.module#OrdersModule'
}

I try following code also, it working
{
path: 'customers',
loadChildren: './customers/customers.module#CustomersModule'
},
{
path: 'orders',
loadChildren: './orders/orders.module#OrdersModule'
}

so question is which is better approach as feature prospective ?

@shiamalon
Copy link

shiamalon commented Sep 19, 2018

@Vino16491

didn't work for me 👎

@daintym0sh
Copy link

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

@mrcleanandfresh
Copy link

Hopefully this may help someone Angular5.x lazyLoad problem, undefined is not a function #23412

@Peter2090
Copy link

When upgrading from Angular 5 to Angular 6 or Angular 7, we had the following errors from lazily-loaded modules, after the upgrade:

Error: Uncaught (in promise): Error: Loading chunk default~[long module name with key suffix] failed.

at

core.js:12632

The solution was to convert ALL our routes from the format

{ path: 'xyz', loadChildren: 'pathtomodule#ModuleName' }

to the lambda expression format

{ path: 'xyz', loadChildren: () => ModuleName }

@klst-speterson
Copy link

@Peter2090 did you run into a "Maximum call stack size exceeded" with the latter of the two approaches? I just started a new Angular 7 project and can't get routing to work with any of the normal (or abnormal) module approaches. Tried what you mentioned, along with the relative path approach, absolute path approach, and all three with and without importing the module in the App Module (I realize it shouldn't be there, figured I'd do my due diligence and test it though).

@Peter2090
Copy link

No...the second approach fixed our 'Error: Loading chunk' errors. It sounds like you have a circular reference. Is there a circular reference in the module imports somehow?

@klst-speterson
Copy link

I've been searching nonstop for a circular reference, but this is literally the first module/route. There's all of like 3 and half lines of code.

@Peter2090
Copy link

All I can suggest is cutting everything out from your project apart from one module to lazy load, but you seem to have done that.

@benmartink
Copy link

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

After many days trying to find a solution, this worked!!

@gcirone
Copy link

gcirone commented Jan 4, 2019

But sorry @benmartink if you do like this { path: 'bing', loadChildren: () => BingModule} the lazy module code is loaded in main bundle. The import break the lazy load beaviour (webpack add this in main chunk not in the lazy one)

@filipesilva Please can you clarify if we need the baseUrl in the sub tsconfig ? Thanks :)

@benmartink
Copy link

Hi @gcirone , yeah you right. I made an architecture where it loads the way you are saying. The only problem I had was that when upgraded angular and several modules related to it, it started to display the error 'Cannot find module "app/xyz/xyz.module". at $_lazy_route_resource lazy'. So, I tried several suggestions found on internet but no one helped until this one!

Btw, I needed to upgrade angular because I wanted to use Angular Materials Design.

@Przemyslaw-Rumin
Copy link

Przemyslaw-Rumin commented Jan 11, 2019

Hi,
I have found that I have small bug inside HTML. I have found it during generation of translation files with command "ng xi18n". After fixing all compilation errors my lazy loading starts working. That error wasn't visible during normal work.

@gcirone
Copy link

gcirone commented Jan 12, 2019

I solved the issue by adding in the angular.json file the lazyModules property and map the same url in the router configuration.

I have to say thanks to Angular guys because now we can load the lazy module direct from the node_modules folder. LOVE IT 🥇

@parasharrajat
Copy link

parasharrajat commented Jan 18, 2019

@gcirone 💯 Where were you when i faced the same problem. After lots of tries and waste of time
I came to same solution.
This is best solution available by @gcirone
I hope there should be a direct channel to talk to angular guys who will say, STOP man you are doing this wrong. This is how we have created it and this is how you gonna use it.

@S2057
Copy link

S2057 commented Jan 25, 2019

this will work
'./login/login.module#LoginModule'
'./dashboard/dashboard.module#DashboardModule'

Actually, I tried in this way. I'm facing an error

@blindstuff
Copy link

blindstuff commented Mar 15, 2019

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.

@izakgl
Copy link

izakgl commented Mar 18, 2019

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.

@schreibse
Copy link

@izakgl: thanks a lot!
I am certain you just saved me a lot of time.
Adding export to my loadConfig factory function (APP_INITIALIZER) solved the error with the lazy loaded modules:
export function loadConfig(config: ConfigService): () => Promise<boolean> { ... }

Path in app-routing.modules looks like:
{ path: 'dashboard', loadChildren: './dashboard/dashboard.module#DashboardModule', },

@danieldanielecki
Copy link

If someone of you is working with Nx monorepo, then please check this answer.

@prashuMishra
Copy link

I was facing the same issue. i found there could be two case for such problem.

  1. Provide the absolute path in routes. i.e {path: 'admin', loadChildren:() => AdminModule }
  2. We don't not need to inject lazy module in App.module.ts. As we importing "RouterModule.forRoot(ROUTES, { useHash: false , scrollPositionRestoration: 'enabled'})"

@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 9, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests