Repository navigation
Description
🐞 Bug report
Command (mark with an x)
- new
- build
- serve
- test
- e2e
- generate
- add
- update
- lint
- xi18n
- run
- config
- help
- version
- doc
Is this a regression?
I don't know. I would guess this is a recent thing arising from the introduction of AOT, Ivy, and the build optimizer.
Description
We faced an issue with an application we were developing where the legacy application had content stored in a database. This content is essentially an Angular template and could not be known at compile-time. The situations and constraints in the project led us to create dynamic components/modules on the fly. This worked beautifully in development and then failed when deployed to production.
In diagnosis, this works as long as the build optimizer is NOT enabled. Having a production build, with the optimizer, but without the buildOptimizer, enabled still works.
I believe I've seen unofficially in other issues that using AOT and JIT together, but since it works with the buildOptimizer disabled, this feels like an issue with the optimizer.
🔬 Minimal Reproduction
Here is a reproduction repo
Once you've npm install'd, you can run the repro this way.
ng serve <-- working
ng serve --configuration=production <--working
ng serve --configuration=production-build-optimized <-- broken.
The only difference between the configurations is the buildOptimizer setting.
You can run all three side-by-side-by-side by adding different --port values.
In a working build, you'll see an additional "Runtime Hello!" message as well as the Angular logo. When broken, those elements will be missing and there will be a console error.
If this isn't a bug, that error message is misleading for this situation.. :)
🔥 Exception or Error
main.7000374ef126bad8069c.js:1 ERROR Error: Uncaught (in promise): Error: Angular JIT compilation failed: '@angular/compiler' not loaded!
- JIT compilation is discouraged for production use-cases! Consider AOT mode instead.
- Did you bootstrap using '@angular/platform-browser-dynamic' or '@angular/platform-server'?
- Alternatively provide the compiler with 'import "@angular/compiler";' before bootstrapping.
Error: Angular JIT compilation failed: '@angular/compiler' not loaded!
- JIT compilation is discouraged for production use-cases! Consider AOT mode instead.
- Did you bootstrap using '@angular/platform-browser-dynamic' or '@angular/platform-server'?
- Alternatively provide the compiler with 'import "@angular/compiler";' before bootstrapping.
at Ae (main.7000374ef126bad8069c.js:1)
at Function.get (main.7000374ef126bad8069c.js:1)
at St (main.7000374ef126bad8069c.js:1)
at new Af (main.7000374ef126bad8069c.js:1)
at ud (main.7000374ef126bad8069c.js:1)
at dd (main.7000374ef126bad8069c.js:1)
at e.md [as compileModuleAndAllComponentsAsync] (main.7000374ef126bad8069c.js:1)
at e. (main.7000374ef126bad8069c.js:1)
at Generator.next ()
at main.7000374ef126bad8069c.js:1
at T (polyfills.a8d522dff2c1a5c4b9db.js:1)
at polyfills.a8d522dff2c1a5c4b9db.js:1
at a (main.7000374ef126bad8069c.js:1)
at l.invoke (polyfills.a8d522dff2c1a5c4b9db.js:1)
at Object.onInvoke (main.7000374ef126bad8069c.js:1)
at l.invoke (polyfills.a8d522dff2c1a5c4b9db.js:1)
at i.run (polyfills.a8d522dff2c1a5c4b9db.js:1)
at polyfills.a8d522dff2c1a5c4b9db.js:1
at l.invokeTask (polyfills.a8d522dff2c1a5c4b9db.js:1)
at Object.onInvokeTask (main.7000374ef126bad8069c.js:1)
🌍 Your Environment
_ _ ____ _ ___
/ \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _|
/ △ \ | '_ \ / _` | | | | |/ _` | '__| | | | | | |
/ ___ \| | | | (_| | |_| | | (_| | | | |___| |___ | |
/_/ \_\_| |_|\__, |\__,_|_|\__,_|_| \____|_____|___|
|___/
Angular CLI: 9.1.4
Node: 13.11.0
OS: darwin x64
Angular: 9.1.4
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router
Ivy Workspace: Yes
Package Version
-----------------------------------------------------------
@angular-devkit/architect 0.901.4
@angular-devkit/build-angular 0.901.4
@angular-devkit/build-optimizer 0.901.4
@angular-devkit/build-webpack 0.901.4
@angular-devkit/core 9.1.4
@angular-devkit/schematics 9.1.4
@ngtools/webpack 9.1.4
@schematics/angular 9.1.4
@schematics/update 0.901.4
rxjs 6.5.5
typescript 3.8.3
webpack 4.42.0
Anything else relevant?
Activity
karwank commentedon May 8, 2020
I'm facing a similar issue. The funny thing is that when I do "ng serve" and having "Live Development Server" started I change the name of "AppModule" to a different name, for example "AppsModule" in both files (app.module.ts and main.ts) it starts to work and vendor.js containst compiler.
jcgillespie commentedon May 8, 2020
@karwank I'm not sure I'm following. You renamed the module and it worked? That didn't work for me, but I might be misunderstanding your steps
karwank commentedon May 11, 2020
It may be related with: #11439
jcgillespie commentedon May 11, 2020
Possibly. I looked at several other issues (many of which are linked in #11439), but this seemed different because it doesn't involve any third-party libraries. This is all just straight Angular functionality. I would agree with a lot of that discussion in 11439: some granularity of control over which optimizations are run would be nice. Better logging or transparency to what IS happening seems like must-have.
karwank commentedon May 12, 2020
After spending a few days on this problem I have found this post: angular/angular#23916 (comment). And point 3 is very sobering. I don't know exactly what you guys want to achieve. But I realized that we only need to have a way to create a dynamic contents which use already existing elements (components). For example:
I realized that I don't need to use JIT for this purpose. Components can be lazy loaded just like Kevin Kreuzer had shown here: https://medium.com/angular-in-depth/lazy-load-components-in-angular-596357ab05d8. So after analyzing these examples: https://github.com/LayZeeDK/ivy-dynamic-rendering, https://stackblitz.com/angular/ovpljlvlyxo, I have written my own service:
alan-agius4 commentedon May 28, 2020
BuildOptimizer, indeed cannot be used with JIT code.
This also seems related to angular/angular#36255 and angular/angular#37216
In your case @jcgillespie, you can avoid using JIT mode and using above approach.
maxtacco commentedon May 28, 2020
@alan-agius4 We are in the same boat as @jcgillespie. The approach described by @karwank is well-known but not viable when you have hundreds of possible template variations.
17 remaining items
Nixon-Joseph commentedon Jul 17, 2020
@loedeman can you provide a quick example of your solution? (trimmed down of course).
dgp1130 commentedon Oct 8, 2020
Spoke with @IgorMinar and @alxhub about this. We don't see any supported use case that benefits from JIT + build optimizer. Build optimizer strips out decorators required by JIT mode, so there's no easy way to make this happen. Build optimizer is intended for production use and JIT has significant bundle size and performance impact due by its very nature, so you'd never have acceptable bundle sizes with this combination anyways (and if you want build optimizer, you clearly care about bundle size). Compiling components at runtime is also an XSS vulnerability in itself, so doing so is not a recommended or supported use case. As a result, we don't think Angular should support such a configuration.
jcgillespie commentedon Oct 8, 2020
@dgp1130 This is a disappointing, if not unexpected, response.
If this isn't going to be a supported scenario, can we get a better, less misleading, error message so people don't waste so much time? The message suggests there is something the user can do to address the issue, but the team has decided this isn't the case.
dgp1130 commentedon Oct 8, 2020
@jcgillespie, agreed that we can do better error messaging here.
Filed #19016 to introduce a better, compile-time message about this.
alxhub commentedon Oct 13, 2020
@FSDRE can you elaborate on what feature you're referring to?
Angular Ivy was specifically designed to enable AOT + JIT to work together. You can build AOT-compiled applications that load the compiler and dynamically compile components on the fly, and can also benefit from build-time code size optimizations (that is, Terser).
The Angular
build-optimizeris something else entirely. It was designed to eliminate things like decorator artifacts that other optimizers could not statically prove were unused. This only makes sense if your codebase is AOT-only - if you're including JIT code then you need those decorators to survive optimization, because the decorators are what trigger the JIT compiler and carry the information needed to compile each class.There's no feature being removed here.
buildOptimizer: truejust doesn't make sense for mixed AOT and JIT application, because its raison d'etre is to strip out the metadata that would otherwise be needed for JIT support, in the name of smaller AOT-only builds.alxhub commentedon Oct 13, 2020
To elaborate a bit more, it is indeed true that
buildOptimizerbeing a binary setting is overly broad - it would theoretically be possible to apply the build-optimizer only to the AOT parts of a hybrid codebase. However, this is not something the CLI currently can do, and there are lots of challenges around knowing which imported libraries can be run through the optimizer and which might be used in a JIT context. It would be nontrivial to support something like this.angular-automatic-lock-bot commentedon Nov 13, 2020
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.