You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Right now, there's only one official Angular CLI way to dynamically load NgModule; through the router configuration and the discovery process for lazy routes.
This discussion is not about dynamic loading of TypeScript files, which works properly already, using the import() keyword. This is exclusively when splitting code at the NgModule boundary, which isn't currently supported.
This has as a consequence that people have to use a fake route if they want to split at the NgModule boundary; e.g. AIO here. Although this work, it's a bad pattern that users shouldn't have to do.
The current suggested design is:
Allow users to add entries to the lazy route from the configuration to emulate the ROUTES provider, then
Use NgModuleFactoryLoader (see example in AIO here) to load the module, which supports both JIT and AOT.
Alternative design was to add refactoring/support of import() keyword, with some annotation support to tell if we should rename to import on AOT. This would require changes in the Angular Compiler which would only make this compatible with Angular 6, while the solution above is fully compatible with Angular 5.
I have the exact same use case as @khaled-ansary and would be very much interested in a solution for this. I understand that tree shaking will not be possible in this case but this does not matter that much to me.
I would also like to use SystemJS and/or a custom NgModuleFactoryLoader implementation to lazy load modules, particularly from another origin. Is there a way of disabling the findLazyRoutes functionality or add an ignore list?
I got super exicted when I got this to work on dev server only to find out that it won't build because of this
Reacted by Michael Black Ritter, Thinh (Thomas), Rob Feng and xuniaoji
Is this issue on the roadmap? Will Ivy release help with that? We are using ui-router in our app and we are forced to include the entire @angular/router module in the bundle, so that vendor routing code size exceeds 60kb min/gzipped, which is insane.
Is this issue on the roadmap? Will Ivy release help with that? We are using ui-router in our app and we are forced to include the entire @angular/router module in the bundle, so that vendor routing code size exceeds 60kb min/gzipped, which is insane.
With Ivy, we will be able to use import('module-name') for lazy-loading and rendering feature components without the router involved.
But Ivy will probably not be production-ready before Angular 9.x according to @IgorMinar.
Reacted by Michael Black Ritter, Pavel Shurygin, Domas Trijonis, Akhil, Djidel Oussama, Carlos Angarita, Michael Bromley, Ilya Borisov and Oleg Varaksin
Very interested in this feature, Our project never uses routing and the main.js is about 5Mb. And the site is obviously heavy though. If we can lazyload modules that would be really amazing!!!
Hey all, I created a component that allows you to lazily load whenever you'd like. Or uses the lazy modules option for an project in the angular.json. it can solve all the issues that I've seen people talking about here.
@aaronfrost Amazing job, thanks. But my modules don't have components. That are mostly services. Not an user triggers the lazy loading, but a config. service by fetching the config. from backend. Imagine a canvas graphic. Some graphics are rendered on initial loading from HTTP call, some at runtime from received messages via WebSocket. Now, I would like to configure what kind of graphic elements the user will see. Every graphic element has a module with renderer, message handling, store slice, etc. How to load such a lazy module programmatically? (not from user interactions)
@aaronfrost your solution works when you have all angular modules available/known at build phase.
Second usecase for which we seem not have a solution is when you dont know those modules at build phase, by this I mean these modules are built/compiled separately from the container application.
Reacted by Lars Gyrup Brink Nielsen, Andrew Robinson and Remi Patriarche
@iamrakesh for your use case wouldn’t work separately build angular elements work best? Then you would only need to know the script and tag name to load them?!
@ova2 can you explain more what you are doing? I don't understand the use case. If the services are lazily loaded, and the lazily loaded code doesn't use the services that are being loaded, then who would be able to consume the service?
@aaronfrost Services are registered themself as multi providers when lazy loaded. They implement an interface from the core module. The core module is not lazy loaded. When a MQTT message has been received from backend, the logic in the core module gets these services over Injector, finds a certain service by received destinationName from the MQTT message and executes some logic on the found service. This just one scenario I'm evaluating right now...
Since Angular 8 we support using dynamic imports (import() syntax) in the router loadChildren split point and have deprecated the string syntax. We also automatically updated CLI projects using ng update. You can see the deprecation here: https://angular.io/guide/deprecations#loadchildren-string-syntax.
In non-Ivy projects, it ends up working the same as before. Internally we rewrite the import('./something.module.ts') to import('something.module.ngfactory.js') to make it work. This rewrite only happens in loadChildren properties. You can read more about it here:
* The importFactory transformation will only see the AST after it is process by NGC.
* You can confirm this with the code below:
*
* const res = ts.createPrinter().printNode(ts.EmitHint.Unspecified, sourceFile, sourceFile);
* console.log(`### Original source: \n${sourceFile.text}\n###`);
* console.log(`### Current source: \n${currentText}\n###`);
*
* At this point it doesn't yet matter what the target (ES5/ES2015/etc) is, so the original
* constructs, like `class` and arrow functions, still remain.
*
*/
.
In Ivy projects however .ngfactory.js files do not exist. If you use import() on a Ivy project and that project was compiled with AOT, the NgModule will contain everything you need to dynamically load it outside the Angular router.
In Angular version 9 Ivy will become the default compiler. Using Ivy together with the import() syntax enables dynamically loading NgModules without any special tooling.
Reacted by Abdalkarim Akilan, mjamin, why520crazy, Vitaly Tkachenko and Huáng Jùnliàng
Activity
filipesilva commentedon Jan 23, 2018
Related existing discussion in #4541, cc @christopherthielen
ValentinFunk commentedon Feb 24, 2018
I suppose this is related? 3be17e7
khaled-ansary commentedon Feb 26, 2018
Hi @hansl, is this issue scenario work with the angular-cli latest version? If it work, could you please give some guide about it?
ManuelEssmeister commentedon Feb 27, 2018
I have the exact same use case as @khaled-ansary and would be very much interested in a solution for this. I understand that tree shaking will not be possible in this case but this does not matter that much to me.
mpicard commentedon Jul 1, 2018
I would also like to use SystemJS and/or a custom NgModuleFactoryLoader implementation to lazy load modules, particularly from another origin. Is there a way of disabling the
findLazyRoutesfunctionality or add an ignore list?I got super exicted when I got this to work on dev server only to find out that it won't build because of this
pshurygin commentedon Nov 16, 2018
Is this issue on the roadmap? Will Ivy release help with that? We are using ui-router in our app and we are forced to include the entire @angular/router module in the bundle, so that vendor routing code size exceeds 60kb min/gzipped, which is insane.
LayZeeDK commentedon Nov 16, 2018
With Ivy, we will be able to use
import('module-name')for lazy-loading and rendering feature components without the router involved.Jason Aden talks about it and shows a demo here:
Angular Ivy by example | Jason Aden | AngularConnect 2018 (timestamped)
But Ivy will probably not be production-ready before Angular 9.x according to @IgorMinar.
webcat12345 commentedon Nov 27, 2018
Very interested in this feature, Our project never uses routing and the main.js is about 5Mb. And the site is obviously heavy though. If we can lazyload modules that would be really amazing!!!
6 remaining items
aaronfrost commentedon Jan 28, 2019
Hey all, I created a component that allows you to lazily load whenever you'd like. Or uses the lazy modules option for an project in the angular.json. it can solve all the issues that I've seen people talking about here.
Check it out: https://www.npmjs.com/package/@herodevs/lazy-af
LayZeeDK commentedon Jan 28, 2019
For true post-deploy, dynamic module loading in Angular versions 2-7+, you have to look into
SystemJsNgModuleLoaderandNgModuleFactoryLoader.aaronfrost commentedon Jan 28, 2019
@LayZeeDK that AND the
lazyModulesoption in the project build options.ova2 commentedon Jan 28, 2019
@aaronfrost Amazing job, thanks. But my modules don't have components. That are mostly services. Not an user triggers the lazy loading, but a config. service by fetching the config. from backend. Imagine a canvas graphic. Some graphics are rendered on initial loading from HTTP call, some at runtime from received messages via WebSocket. Now, I would like to configure what kind of graphic elements the user will see. Every graphic element has a module with renderer, message handling, store slice, etc. How to load such a lazy module programmatically? (not from user interactions)
iamrakesh commentedon Jan 28, 2019
@aaronfrost your solution works when you have all angular modules available/known at build phase.
Second usecase for which we seem not have a solution is when you dont know those modules at build phase, by this I mean these modules are built/compiled separately from the container application.
denisyilmaz commentedon Jan 28, 2019
@iamrakesh for your use case wouldn’t work separately build angular elements work best? Then you would only need to know the script and tag name to load them?!
iamrakesh commentedon Jan 28, 2019
@denisyilmaz We did consider Angular Elements, but didn't evaluate thoroughly and decided to wait for Ivy to become available and decide then
aaronfrost commentedon Jan 28, 2019
@ova2 can you explain more what you are doing? I don't understand the use case. If the services are lazily loaded, and the lazily loaded code doesn't use the services that are being loaded, then who would be able to consume the service?
ova2 commentedon Jan 28, 2019
@aaronfrost Services are registered themself as multi providers when lazy loaded. They implement an interface from the core module. The core module is not lazy loaded. When a MQTT message has been received from backend, the logic in the core module gets these services over Injector, finds a certain service by received destinationName from the MQTT message and executes some logic on the found service. This just one scenario I'm evaluating right now...
aaronfrost commentedon Jan 28, 2019
If it's using multiproviders, that makes sense. This should load that as well, then. I will try it out and let you know.
nasreddineskandrani commentedon Jan 30, 2019
@aaronfrost if you can publish this case of
multiprovidersonline i am interested on it to learn (never faced this usecase)filipesilva commentedon Oct 9, 2019
Since Angular 8 we support using dynamic imports (
import()syntax) in the routerloadChildrensplit point and have deprecated the string syntax. We also automatically updated CLI projects usingng update. You can see the deprecation here: https://angular.io/guide/deprecations#loadchildren-string-syntax.In non-Ivy projects, it ends up working the same as before. Internally we rewrite the
import('./something.module.ts')toimport('something.module.ngfactory.js')to make it work. This rewrite only happens inloadChildrenproperties. You can read more about it here:angular-cli/packages/ngtools/webpack/src/transformers/import_factory.ts
Lines 16 to 55 in 0d70565
In Ivy projects however
.ngfactory.jsfiles do not exist. If you useimport()on a Ivy project and that project was compiled with AOT, the NgModule will contain everything you need to dynamically load it outside the Angular router.In Angular version 9 Ivy will become the default compiler. Using Ivy together with the
import()syntax enables dynamically loading NgModules without any special tooling.angular-automatic-lock-bot commentedon Nov 9, 2019
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.