Repository navigation
Description
I'm submitting a...
[ ] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report
[X] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
Current behavior
Router Module is optional and, depending on the nature of the app, it does not naturally fit.
If we don't use the RouterModule, I can't see an easy way to take advantage of the "lazy loading" feature for modules.
I'd like to, somehow, identify an NgModule to be "lazy loaded" at definition time (just like you define its providers, etc).
Once the module has been marked as "lazy loaded", the build should generate an independent chunk for it and that module becomes eligible for being lazy-loaded at some execution time.
Of course, If I have the choice of marking a module "lazy", I also need a mechanism to manually load those "lazy loaded" modules and start using them.
In summary, the feature request is: make the "lazy loading" feature available to developers outside the RouterModule since this module is optional but the feature should still be available.
Of course this should output AOT compatible chunks, etc, just like the RouterModule internally does.
Expected behavior
In summary, the feature request is: make the "lazy loading" feature available to developers outside the RouterModule since this module is optional but the feature should still be available.
Of course this should output AOT compatible chunks, etc, just like the RouterModule internally does.
Minimal reproduction of the problem with instructions
What is the motivation / use case for changing the behavior?
Our application and functionally can not be Router driven thus we need some way to make use of the "lazy loading" strategy that is internally used by the Router.
Environment
Angular version: X.Y.Z
Browser:
- [ ] Chrome (desktop) version XX
- [ ] Chrome (Android) version XX
- [ ] Chrome (iOS) version XX
- [ ] Firefox version XX
- [ ] Safari (desktop) version XX
- [ ] Safari (iOS) version XX
- [ ] IE version XX
- [ ] Edge version XX
For Tooling issues:
- Node version: XX
- Platform:
Others:
Activity
Toxicable commentedon Jul 13, 2017
You can already do this, here is a small example of how
This is almost the exact same method the router uses to lazy load except it simply provides a nice API to use it, however, this only works for AOT, you'd need extra logic to support JIT.
josephliccini commentedon Jul 16, 2017
Hi!
I had left this idea a while ago but was making some progress on a solution.
(@Toxicable we chatted about this a while ago in the gitter.im angular room.)
I think it will require a new webpack loader to get it to work cleanly, but here's the basic idea.
<dynamic-lazy-load>component:@NgModule()in format:I had a prototype working but abandoned as I had some other stuff to take care of and hit a blocker on AoT.
And the hackiest part was I had to trick the Webpack loader into thinking this was a loadChildren for the router, which is where I gave up because I couldn't get AoT working.
I did have it working when I hardcoded to JiT like this:
I haven't tested this code in a while, but I can maybe update with a demo sometime when I have time.
This feature would be great to have as something easier and standardized, as I've been doing some React coding on the side and they can lazy load components within a view pretty easily.
Some problems I can foresee:
providers,pipes, etc. in the lazy module..'MyLazyComponent'in the example.I just thought I'd post and share my exploration as I've seen this question a lot. By no means am I posting above code as a solution (again, this was just a hacky prototype I tried)
aalbericio commentedon Jul 20, 2017
Hello guys,
I aprreciate the efforts of offering a workaround on this (I will more than probably use a custom hack on this following your instructions) but I still see the advantage of declaring a Module like:
@NgModule({
imports: [ MyLazyComponent ],
exports: [ MyLazyComponent ],
entryComponents: [ MyLazyComponent ],
lazy: true
})
... and, of course, having a programmatic API to load this/or any Module
ModuleManager.loadModule(....).then(...)
... and, of course, this should work with JiT/AOT, serve/build, etc
I know Ionic and others like you have implemented their custom solution but I can bet adding this feature makes Angular (and any other based solution) just better.
Toxicable commentedon Jul 20, 2017
I made another demo here https://plnkr.co/edit/ZGC82G9u10EQFYFvvRMB?p=preview
it uses
NgModuleFactoryLoaderwhich Angular already provides for you to handle lazy loading modulesaalbericio commentedon Jul 20, 2017
Hello,
Okay, that will load the module and instantiate its entry component but how does that solution play in conjunction with the DI/Injectors system and what about the build? Will the build generate a separate chunk for the LazyModule?
I would like not to lose any feature provided both by the DI/Injectors system (eager/lazy) and the build process.
I still firmly believe that this feature should be provided by the framework and open to developers.
Toxicable commentedon Jul 20, 2017
@aalbericio It works the same as the Router. Seprate Chunk with child Injector.
Is the example I provided to concise enough?
aalbericio commentedon Jul 20, 2017
Ok. I'm going to test it under an isolated environment and tell you. I just wanted to confirm those points before testing it.
Thanks very much, Fabian.
mlc-mlapis commentedon Jul 20, 2017
@Toxicable ... not sure but the building could be a problem. You will need probably to define all routes with lazy module paths even if you don't use them directly to get right chunks.
Toxicable commentedon Jul 20, 2017
@mlc-mlapis You're right I was missing a few small components for it to work with the CLI and Webpack. I've updated the demo with this now working in plunkr, CLI and with AOT.
https://plnkr.co/edit/ZGC82G9u10EQFYFvvRMB?p=preview
mlc-mlapis commentedon Jul 20, 2017
@Toxicable ... great ... and now there will be always the right answer for every one who has a request for a new feature or API ... to allow programmatical way how to load and use lazy loaded modules.
It is so simple that it couldn't be more simpler.
josephliccini commentedon Jul 20, 2017
@Toxicable this is great!! Thanks for doing this!
Toxicable commentedon Jul 20, 2017
I made one more little update to it just to show how you can use the paths to the lazy modules without any duplication aswell as how you provide in a feature module aswell.
https://plnkr.co/edit/ZGC82G9u10EQFYFvvRMB?p=preview
@josephliccini No problem, hope it's helped
josephliccini commentedon Jul 20, 2017
Would something like this be able to be placed into a
ngx-lazy-loador something? If I find time I'd like to make it easier for folks and our own engineers to useEDIT: not asking you to do so, but I am interested on if it its possible
Toxicable commentedon Jul 20, 2017
@josephliccini it would be possible to put this into a lib.
However since most of it is config you'd have to provide it would only contain
DynamicComponentthe rest of it you'd still have to provide yourself.55 remaining items
[-]Make lazy loading available outside the Router Module[/-][+]Ergonomic component-level code splitting and lazy loading[/+]jelbourn commentedon Oct 9, 2020
Just closed a bunch of issues that @atscott and I believe are asking for the same general idea. Updated the title of this issue to reflect that underlying concept. #22243 and #13218 seem to be very similar, need to look into further whether they can be combined into this.
KarlXOL commentedon Oct 10, 2020
Checked this approach a while ago.
This solution has its very pitfalls and limitations and is no solution for "feel-good" dynamic loading at runtime.
For example you have to care of component instantiation, parameter passing, etc...
nasreddineskandrani commentedon Oct 12, 2020
@KarlXOL it's only a solution and i do agree with you => Angular team should think about something more efficient and nice to achieve the desired result if possible.
jstoppa commentedon Feb 8, 2021
I'd just like to share s solution that worked for me for lazy loading components at runtime.
My use case is that I've got an application that loads components programmatically using the Dynamics Component Loader, it was never architected to use the router and the number of components that can be loaded programmatically grew over time, they are loaded conditionally based on configuration/feature flags. The problem is that all these components are not lazy loaded and they ended up bloating the main bundle.
I can’t really rearchitect the entire app to user the router which would require a lot of time and effort so lazy loading programmatically is key for my use case.
I initially tried loading these components like the below:
This works but it would bring other problems at runtime:
I searched and I found a few approaches like this or this, which requires putting a module inside the component file and loading the module using the compiler.
My approach was to reference the component and the module from the tsconfig.json’s paths via a proxy file that references them…
the public-api.ts would reference the component and the module
and then load the component using the reference in the tsconfig.json file.
The sub.module.ts file will contain the modules that I need to solve the errors I was getting.
This approach worked really well for me, I had to do little refactoring of my application and managed to reduce the main bundle size by 25% 😊
I hope it helps someone else
petebacondarwin commentedon Nov 26, 2021
This should be made possible by the "standalone components" project.
pkozlowski-opensource commentedon Jun 30, 2022
Angular's standalone components implemented in Angular v14 and other changes we've been doing around
ComponentFactoryResolvergreatly improve the component-level, lazy-loading story.As an example, lazy-loading a standalone component and rendering it boils down to:
With the the RFC: Standalone components, directives and pipes - making Angular's NgModules optional implemented we can consider that the stated issue is solved!
angular-automatic-lock-bot commentedon Jul 31, 2022
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.