Reputation: 71
I am trying to lazy load NgModule from a library. I have a ng app, which contains some libraries (projects). This libraries are reused in some other projects. The problem is i can't find a solution, that would work with both jit and aot, and compiled/not compiled library.
file structure is like this
app
-projects
--lib
---(lib files)
-src
--(app files)
AppModule has routing, which looks like this
const routes: Routes = [
{
path: 'eager',
children: [
{
path: '',
component: LibComponent // component imported from lib
},
{
path: 'lazy',
loadChildren: 'lib/src/lib/lazy/lazy.module#LazyModule' // module i want to load lazily
}
]
}
];
if i use it like this, i get runtime error when trying to navigate to lazy route in jit (aot works correctly):
ERROR Error: Uncaught (in promise): TypeError: undefined is not a function TypeError: undefined is not a function
this comment https://github.com/angular/angular-cli/issues/9488#issuecomment-370065452 suggests not to include LazyModule to any barrel files, but if i exclude it from public_api of library i get build error:
ERROR in ./projects/lib/src/lib/lazy/lazy.module.ts
Module build failed (from ./node_modules/@ngtools/webpack/src/index.js):
Error: C:\projects\lazy_minimal\lazy-minimal\projects\lib\src\lib\lazy\lazy.module.ts is missing from the TypeSc
ript compilation. Please make sure it is in your tsconfig via the 'files' or 'include' property.
at AngularCompilerPlugin.getCompiledFile (C:\projects\lazy_minimal\lazy-minimal\node_modules\@ngtools\webpac
k\src\angular_compiler_plugin.js:752:23)
at plugin.done.then (C:\projects\lazy_minimal\lazy-minimal\node_modules\@ngtools\webpack\src\loader.js:41:31
)
at process._tickCallback (internal/process/next_tick.js:68:7)
is there any way to make it work for both aot and jit?
Upvotes: 7
Views: 9663
Reputation:
There is an issue in Angular-CLI about loading compiled library in node_modules in lazy loading way. The following is the workaround suggested by Alan Agius
This thread was opened a while ago. Having so comments makes it hard for people to find information in anything but the latest comments. But on the other hand I don't think most people would go through all of the comments anyway. New users that see this thread mostly read the first and latest comments and lose things said in between.
So for the reasons stated above (high volume of comments, hidden comments, hard to report and inform people) I'm locking this issue to prevent this comment from being lost as new comments come in.
Thank you to everyone that reported and helped diagnose the problems and provided workarounds.
Our recommended approach to lazy load a library within an angular workspace or node modules, is to use a proxy/wrapper module. With this approach lazy loading will works in both JIT and AOT mode. There are other solutions that work solely in AOT mode such as tsconfig imports however for a better development experience we don't encourage this.
Below find an example of the recommended approach;
lazy/lazy.module.ts
import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; import { LibModule, LazyComponent } from 'my-lib'; @NgModule({ imports: [ LibModule, RouterModule.forChild([ { path: '', component: LazyComponent, pathMatch: 'full' } ]) ] }) export class LazyModule { }
app.module.ts
import {BrowserModule} from '@angular/platform-browser'; import {NgModule} from '@angular/core'; import {RouterModule} from '@angular/router'; import { AppComponent } from './app.component'; import { HomeComponent } from './home/home.component'; @NgModule({ declarations: [ AppComponent, HomeComponent, ], imports: [ RouterModule.forRoot([ { path: '', component: HomeComponent, pathMatch: 'full'}, { path: 'lazy', loadChildren: './lazy/lazy.module#LazyModule'}, ]), ], bootstrap: [AppComponent] }) export class AppModule { }
Upvotes: 8