In Angular 7 version Lazy Loading is not working

Viewed 7717

I have updated my angular 6 version to angular 7 version. Now I am getting error when I try to navigate to 'http://localhost:4200/pages'. I am use lazy loading route concept in my application.

Error:-

core.js:12584 ERROR Error: Uncaught (in promise): Error: Cannot find module './Pages/Test/Test.module' Error: Cannot find module './Pages/Test/Test.module' at $_lazy_route_resource lazy namespace object:5 at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:388) at Object.onInvoke (core.js:14143) at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:387) at Zone.push../node_modules/zone.js/dist/zone.js.Zone.run (zone.js:138) at zone.js:872 at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421) at Object.onInvokeTask (core.js:14134) at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:420) at Zone.push../node_modules/zone.js/dist/zone.js.Zone.runTask (zone.js:188) at $_lazy_route_resource lazy namespace object:5 at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:388) at Object.onInvoke (core.js:14143) at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:387) at Zone.push../node_modules/zone.js/dist/zone.js.Zone.run (zone.js:138)

app-routing.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Routes} from '@angular/router';

export const AppRoutes : Routes = [
 {
  path : '',
  redirectTo: 'test',
  pathMatch: 'full',
 }
 {
  path: 'test',
  loadChildren: './Pages/test/test.module#TestModule'
 }      
]

Tell me, how to solved this error.

4 Answers

After trying many changes, I found that my app.routing.ts should be like this:-

import { TestModule } from './Pages/test/test.module';

 export const AppRoutes : Routes = [
 {
  path : '',
  redirectTo: 'test',
  pathMatch: 'full',
 }
 {
  path: 'test',
  loadChildren: () =>  TestModule
 }      
]

After changes this works perfect for me.

The accepted answer is wrong and should actually be removed because it is misleading and when adopted, can lead to unexpected behavior and performance issues. The problem is that as soon as you import a module (first line in your code) like import { TestModule } from './Pages/test/test.module'; the module will be loaded directly (eagerly). regardless of what you provide to loadChildren.

Please see a correct approach below:

 export const AppRoutes : Routes = [
 {
  path : '',
  redirectTo: '/test',
  pathMatch: 'full',
 }
 {
  path: 'test',
  loadChildren: () => import('./Pages/test/test.module').then(mod => mod.TestModule)
  }      
]

Like this, the module gets imported (loaded) only when the provided function in loadChildren is called, which happens only when you navigate to /test. As you see, i removed the initial import import { TestModule } from './Pages/test/test.module'; from the beginning of the code.

Hope this helps!

-Ivan

For starts you should always place the paths starting with the most restrictive ones first and eventually the default path... Then, you didn't share your module code, we can only assume that you readily have a test-routing.module.ts file that correctly defines the components to load when the paths in that module are called/matched.

app-routing.module.ts

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { Routes} from '@angular/router';

export const AppRoutes : Routes = [
 {
  path: 'test',
  loadChildren: './Pages/test/test.module#TestModule'
 }, {
  path : '',
  redirectTo: 'test',
  pathMatch: 'full',
 }      
]

test-routing.module.ts

import { NgModule } from "@angular/core";
import { Routes, RouterModule } from "@angular/router";

import { TestComponent } from "./test/test.component";

const routes: Routes = [
  {
    path: "",
    component: TestComponent
  }
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class TestRoutingModule {}

In order to eagerly load modules with a function reference when AOT enabled for Angular 7, you need to create an NgFactory module as you can see from this PR - https://github.com/angular/angular/pull/13909.

A working solution for me was creating a clone of my module and adding .ngfactory postfix to the filename and also adding NgFactory postfix to the module class name.

import { FirstPageModuleNgFactory } from '../pages/first-page.module.ngfactory';
import { SecondPageModuleNgFactory } from '../pages/second-page.module.ngfactory';

export function loadFirstPageModule() {
    return FirstPageModuleNgFactory;
}

export function loadSecondPageModule() {
    return SecondPageModuleNgFactory;
}

const routes: Routes = [
    {
        path: '',
        component: HomePageComponent,
        children: [
            {
                path: '',
                redirectTo: 'first',
                pathMatch: 'full',
            },
            {
                path: 'first',
                loadChildren: loadFirstPageModule,
            },
            {
                path: 'second',
                loadChildren: loadSecondPageModule,
            },
        ],
    },
];
Related