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
{{ message }}
Repository navigation
AOT broken when using loadChildren and a function : Replace modules import by modules factories ? #4192
When I try to build my app with AOT since I'm using loadChildren with a function it breaks (not at compilation but when running the app in the browser, complaining that r.create is not a function).
I'm wondering if this can be done by angular-cli ? Or as soon as we use loadChildren with a function (don't want AOT or AOT is broken due to some other bugs for example) we have to manually do that ?
Reacted by Sam Verschueren, Tomasz Kucharzyk, drew moore, Mike Hill, Alexandru Sfirlogea, McNull, Andrey, Gildas Niyigena, Jonas Praem, Daniel Ormeño and 7 more
I have been involved in attempts to get something like this working. The core team guys suggest it's a tough nut to crack. It's something I imagine the compiler-cli should be doing, changing the output of the compilation, it is compilation (translation) when you think about it.
For now, the workaround is to change the loadChildren assignment to a string (lazy loading), but keep the function around to make the module get included in the same bundle instead of a separate one. Keeping the exported function not just the import makes sure it doesn't get tree shaked / minified.
Like:
import { ProfileModule } from './profile/profile.module';
// Do not delete. Used to ensure ProfileModule is loaded in the same bundle.
// Referencing the function directly in `loadChildren` breaks AoT compiler.
export function loadProfileModule() {
return ProfileModule;
}
export const routes: Routes = [
// ... other routes ...
{ path: 'profile', loadChildren: './profile/profile.module#ProfileModule' }
];
Check the app-routing.module.ts in my routing test project for a working example:
Reacted by Tomasz Kucharzyk, Tim Gaines, drew moore, Alan Tai, Wassem Keddah, McNull, Alan Grosz, Andrii Mykhailov, Daniele Stefano Ferru, Tim Malabuyo and 11 more
Reacted by Maxime, Boris Lemke, drew moore, McNull, Alan Grosz, Daniele Stefano Ferru, Andrea Medda Campus, mabo753, Tess Grankina, antoine beauᵛᵃᴵˢ⁻lacᵃˢˢᵉ and 4 more
I'm attempting to use AOT with my app, which is quite large and lazy loads many modules.
I'm following the official AOT cookbook by using ngc and rollup. As was discussed in #11075, rollup does not even support lazy loading, so I'm looking for another way to compile my app.
The issue is that ngc by itself does not actually build any of my lazy loaded modules because (I'm assuming) they are not directly imported with an import statement but instead specified as a loadChildren string.
At runtime, Angular correctly requests the Factory for the module instead of the Module itself, but the module doesn't exist so the routing fails.
Is this the expected behavior of ngc? Is there no official way to compile the factories lazy loaded modules?
Reacted by Giancarlo Soverini, Michael Peiffer and mgpeng
@noamichael AOT and lazy loading should work just fine with the build system coming builtin with the CLI.
This issue is about non-lazy-loading, and as I mentioned in previous comment, a workaround is to trick AoT to think that it's lazy-loading the module (because again, lazy-loading does work), while also having a dummy use of the module so that it still gets included in the main bundle.
@Meligy I was having this issue as well and with the recommended workaround of yours my app started to work again. Could you kindly explain if we still get the benefits of lazy loading when using this workaround? How is my app being optimised when using loadChildren but still importing the module in a dummy export function?
update
After re-reading your las comment you mentioned that this is about non-lazy-loading. So what is the benefit of using this instead of just import the module with it's own routing in the main app.module?
This way, you contact module itself defines the routes where the contact and contact details are accessible, but your app itself defines what part comes in front of that. You contact module doesn't need to know whether it is /contact or /mycontacts.
Reacted by Alexandre Annic, Jonas, Tony Franzese and Allen
@SamVerschueren okay so based on your explanation, this has no performance benefit beside that the ContactModule is more "modular" as it does not depend on a certain path. You could just plug this into any project and define it's path, correct?
This issue is about non-lazy-loading, and as I mentioned in previous comment, a workaround is to trick AoT to think that it's lazy-loading the module (because again, lazy-loading does work), which having a dummy use of the module so that it still gets included in the main bundle.
Also curious of status. Having to disable AoT in nativescript builds with lazy-loading children. Would be nice to get the performance boost of AoT in mobile app.
Function with loadChildren is still not working with AOT as of 9/6/2018, CLI version 6.1.1 - have to switch to lazy loaded path to enable AOT and bypass error of 'Runtime compiler is not loaded'.
Reacted by Borja Ruiz Torres, shmorhun, Vladimir, David Boothe, aider, Oliver Sahner, Ernest, Ahmet Hatipoğlu, Krzysztof Karol, raphael22 and 6 more
The CLI with ng update refactored the loadChildren since Angular 8 from a string (AOT fine) to Arrow function but the error is still here... "Error: Runtime compiler is not loaded".
What the heck ?
I undo the changes to use the string syntax and to make it works once again.
And for many others, I'd search for issues specific to that. I'd like to note that with the new import syntax, I can also now successfully use variables in the strings, and everything still works with AOT:
@devbenzy Yeah, actually I was premature, the only syntax that's supported is exactly what I had in the first part of my post, (single quotes only, no template literals), see this conversation here:
Thanks for the help @chriszrc.
I used the syntax you recommended to me.
I hope they will fix it to allow all syntaxes because this is causing so much struggle for nothing important...
Reacted by ZRSA - internal
angular-automatic-lock-bot commented on Sep 9, 2019
Activity
Meligy commentedon Jan 24, 2017
I have been involved in attempts to get something like this working. The core team guys suggest it's a tough nut to crack. It's something I imagine the compiler-cli should be doing, changing the output of the compilation, it is compilation (translation) when you think about it.
For now, the workaround is to change the
loadChildrenassignment to astring(lazy loading), but keep the function around to make the module get included in the same bundle instead of a separate one. Keeping theexported function not just the import makes sure it doesn't get tree shaked / minified.Like:
Check the
app-routing.module.tsin my routing test project for a working example:https://github.com/meligy/routing-angular-cli
Specifically:
https://github.com/Meligy/routing-angular-cli/blob/deep-lazy-loading/src/app/app-routing.module.ts#L18
filipesilva commentedon Jan 24, 2017
@hansl can you weigh in?
maxime1992 commentedon Jan 24, 2017
@Meligy I never thought that keeping an unused import would work for AOT !
I just tried what you proposed in my (large) app and it worked on the first try 👍 !
Thanks a lot, this is a super news while the discussion is going on 😄 !
noamichael commentedon Jan 25, 2017
I'm attempting to use AOT with my app, which is quite large and lazy loads many modules.
I'm following the official AOT cookbook by using
ngcandrollup. As was discussed in #11075, rollup does not even support lazy loading, so I'm looking for another way to compile my app.The issue is that
ngcby itself does not actually build any of my lazy loaded modules because (I'm assuming) they are not directly imported with an import statement but instead specified as aloadChildrenstring.At runtime, Angular correctly requests the Factory for the module instead of the Module itself, but the module doesn't exist so the routing fails.
Is this the expected behavior of
ngc? Is there no official way to compile the factories lazy loaded modules?Meligy commentedon Jan 26, 2017
@noamichael AOT and lazy loading should work just fine with the build system coming builtin with the CLI.
This issue is about non-lazy-loading, and as I mentioned in previous comment, a workaround is to trick AoT to think that it's lazy-loading the module (because again, lazy-loading does work), while also having a dummy use of the module so that it still gets included in the main bundle.
fix(frontend): temporary use lazy loaded routes with aot (fixes #1)
borislemke commentedon Feb 24, 2017
@Meligy I was having this issue as well and with the recommended workaround of yours my app started to work again. Could you kindly explain if we still get the benefits of lazy loading when using this workaround? How is my app being optimised when using
loadChildrenbut still importing the module in a dummyexport function?update
After re-reading your las comment you mentioned that this is about non-lazy-loading. So what is the benefit of using this instead of just import the
modulewith it's own routing in the mainapp.module?SamVerschueren commentedon Feb 24, 2017
@borislemke Because this way your feature module doesn't need to know what path is being used to access it.
For example, suppose you have a
ContactModule. You could define the routing like thisThis way your contact module itself defines that the URL is
/contact. If you take this approach, you will define your routes like thisAnd in your app routing, you then load the contact module as child
This way, you contact module itself defines the routes where the contact and contact details are accessible, but your app itself defines what part comes in front of that. You contact module doesn't need to know whether it is
/contactor/mycontacts.borislemke commentedon Feb 24, 2017
@SamVerschueren okay so based on your explanation, this has no performance benefit beside that the
ContactModuleis more "modular" as it does not depend on a certain path. You could just plug this into any project and define it's path, correct?SamVerschueren commentedon Feb 24, 2017
Yes, exactly!
steve3d commentedon Mar 10, 2017
so, any updates here?
Does this means there is no way to use AOT with router lazy loading(loadChildren) together?
SamVerschueren commentedon Mar 10, 2017
This has nothing to do with lazy loading.
From @Meligy
maxime1992 commentedon Mar 10, 2017
@steve3d AOT works well with lazy loading. The problem is when you want to load a module like that :
10 remaining items
barisbikmaz commentedon Mar 14, 2018
Any news on this ?
I've angular-cli 1.7.1 and have still the problem that I can't run AOT builds when using loadChildren with factory method.
I can switch to lazy loading by path but the my startup performance will decrease. Would be very cool if you can fix this.
r0zar commentedon Mar 18, 2018
Also curious of status. Having to disable AoT in nativescript builds with lazy-loading children. Would be nice to get the performance boost of AoT in mobile app.
fixed AOT-error with not lazy loaded modules
aburht commentedon Aug 14, 2018
Error: Runtime compiler is not loaded
I still see, this is broken when you run the app with aot enabled
{path: 'helper', loadChildren: () => HelperModule }
@filipesilva any idea if this would be supported anytime sooner ?
wctiger commentedon Sep 6, 2018
Function with loadChildren is still not working with AOT as of 9/6/2018, CLI version 6.1.1 - have to switch to lazy loaded path to enable AOT and bypass error of 'Runtime compiler is not loaded'.
unspike commentedon Jan 20, 2019
Angular 7.2 still actual, no way to use AOT with
loadChildren = () => ModuleNameromko391 commentedon Feb 28, 2019
I'm wondering WHY do guys develop/add new features while having such an
important thingsbroken.C0ZEN commentedon Jun 4, 2019
The CLI with
ng updaterefactored the loadChildren since Angular 8 from a string (AOT fine) to Arrow function but the error is still here... "Error: Runtime compiler is not loaded".What the heck ?
I undo the changes to use the string syntax and to make it works once again.
chriszrc commentedon Jun 26, 2019
@C0ZEN lazy loading with loadChildren and functions is working for me in 8:
ref - https://blog.angularindepth.com/automatically-upgrade-lazy-loaded-angular-modules-for-ivy-e760872e6084
devbenzy commentedon Jun 27, 2019
but this doesn't
loadChildren: () => {reutrn import('./lazy/lazy.module').then(m => m.LazyModule)}
chriszrc commentedon Jul 2, 2019
@devbenzy Yeah, actually I was premature, the only syntax that's supported is exactly what I had in the first part of my post, (single quotes only, no template literals), see this conversation here:
#14763 (comment)
C0ZEN commentedon Jul 2, 2019
Thanks for the help @chriszrc.
I used the syntax you recommended to me.
I hope they will fix it to allow all syntaxes because this is causing so much struggle for nothing important...
angular-automatic-lock-bot commentedon Sep 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.