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?
To lazy load Angular modules, use loadChildren (instead of component ) in your AppRoutingModule routes configuration as follows. content_copy const routes: Routes = [ { path: 'items', loadChildren: () => import('./items/items.module').then(m => m.ItemsModule) } ];
Lazy-Load the Library (micro-app)Use the new import syntax. We import the module that is located in the @lazy/security-app library project (as if it were a package courtesy of Nx --npm-scope @lazy). When I created the workspace, I used the --npm-scope option to create the scope lazy.
Lazy Loading is the technique of loading the module or data on demand. It helps us to better the application performance and reduce the initial bundle size of our files. The initial page loads faster and we can also split the application into the logic chunks which can be loaded on demand.
Therefore, to make angular understand the need to load BackendService , the new steps are: lazy load the module, compile it to notify Angular about its dependencies, finally, through the compiled module, we access the component and then add it to the container.
There is a opened issue in Angular-CLI about loading compiled library in node_modules in lazy loading way here, it still open.
last workaround proposed is:
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;
first 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 { }
then 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 { }
angular locked and limited conversation to collaborators on Jan 10
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With