Closed lacolaco closed 3 years ago
@gatimus you resolved problem?
No, I insured I had decorated with @NgModule as well, same results.
Error: Unexpected value 'e' imported by the module 'e'. Please add a @NgModule annotation.
private createCompoent(template: string) {
@CustomComponent({
selector: 'dynamic-template',
template: template
})
class DynamicComponent { }
return DynamicComponent ;
}
private createModule(modules: any[], componentType: any) {
const metadata = {
imports: [...modules],
declarations: [componentType]
};
@NgModule(metadata)
@CustomNgModule(metadata)
class DynamicModule { }
return DynamicModule;
}
public async render(template: string) {
const compoent = this.createCompoent(template);
const module = this.createModule([RouterModule], compoent);
const moduleWithComponentFactories = await this.compiler.compileModuleAndAllComponentsAsync(module);
const compoentFactory = moduleWithComponentFactories.componentFactories[0];
this.view.clear();
this.view.createComponent(compoentFactory);
}
I used your code. I did not get problem
How you get this.compiler
?
What version you use in ng-cli and angular?
[alekcei@localhost AotAndJit]$ ng -v
_ _ ____ _ ___
/ \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _|
/ △ \ | '_ \ / _` | | | | |/ _` | '__| | | | | | |
/ ___ \ | | | | (_| | |_| | | (_| | | | |___| |___ | |
/_/ \_\_| |_|\__, |\__,_|_|\__,_|_| \____|_____|___|
|___/
@angular/cli: 1.1.2
node: 8.1.2
os: linux x64
@angular/animations: 4.2.3
@angular/common: 4.2.3
@angular/compiler: 4.2.3
@angular/core: 4.2.3
@angular/forms: 4.2.3
@angular/http: 4.2.3
@angular/platform-browser: 4.2.3
@angular/platform-browser-dynamic: 4.2.3
@angular/router: 4.2.3
@angular/cli: 1.1.2
@angular/compiler-cli: 4.2.3
@angular/language-service: 4.2.3
I used new project
I updated my example to version 4.2.5 Now asks @CustomInput
Can't bind to 'from' since it isn't a known property of 'ui-select'.
1. If 'ui-select' is an Angular component and it has 'from' input, then verify that it is part of this module.
2. If 'ui-select' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.
3. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component. ("king !!!!!!!!</ui-button>
Although @Input is
@Alekcei
this.compiler
is injected with:
export function compilerFactory() {
return new JitCompilerFactory([{ useDebug: false, useJit: true }]).createCompiler();
}
providers: [{ provide: Compiler, useFactory: compilerFactory }]
versions
@angular/cli: 1.1.3
node: 8.1.3
os: win32 x64
@angular/animations: 4.2.5
@angular/common: 4.2.5
@angular/compiler: 4.2.5
@angular/core: 4.2.5
@angular/flex-layout: 2.0.0-beta.8
@angular/forms: 4.2.5
@angular/http: 4.2.5
@angular/material: 2.0.0-beta.6
@angular/platform-browser: 4.2.5
@angular/platform-browser-dynamic: 4.2.5
@angular/router: 4.2.5
@angular/cli: 1.1.3
@angular/compiler-cli: 4.2.5
@angular/language-service: 4.2.5
I'm going to try to duplicate with a simpler project.
I need your simple project, Plese add repo
@Alekcei I omitted what I though wasn't relevant. On line const module = this.createModule([RouterModule], compoent);
I also imported an other module const module = this.createModule([RouterModule, MyModule], compoent);
. It seems MyModule
also needs to be decorated with both NgModule
and CustomNgModule
.
@gatimus Yes, This must be done for all components and module.
I want to try to collect everything via webpack. He' don't remove decorators.
It should not remove decorators.
decorator @Input on fields also removed. I do not know how to create @CustomInput()
@Paladinium :I don't think we are actually getting what is required. Basically what all you are doing can be achieved with the following javascript code itself and we don't need runtime compiler for that. The aot bundled library file whenever be loaded it will take care to scan the document and rendered accordingly:
document.getElementById("#someidentifier").innerHTML = "<some-component [color]="\'red\'" [text]="\'Created with JIT\'">"
using templateContent you are actually adding component selector html only.
But when we say dynamically compiled and rendered component what we should be able to achieve like the following :
<some-component template="!html template-url or template-reference" controller="!typescript controller class reference=''>"
@vasuneet I did the following.
<div id="someidentifier"></div>
<a [routerLink]="['another-route']">some link</a>
const html = `<p>...some text...<a [routerLink]="['another-route']">some link</a>...some text...</p>`;
document.getElementById('someidentifier').innerHTML = html;
The "some link" out side the div navigated and the "some link" inside had no behavior.
document.getElementById('someidentifier').innerHTML = html;
Equivalently [innerHtml]
<div [innerHTML]="html">
@Alekcei I agree. the solution provided in attachment here is not using Runtime compiler actually. @Paladinium if you can provide the sample code of using RuntimeCompiler with AOT. It will be good.
@alexzuza thanks for sharing. This is example of dynamically injecting the already build component. I am looking for the solution for rendering dynamic component which template we will decide on runtime and so we also require runtimecompiler along with AOT. The provided solution is not the example of runtimeCompiler along with AOT.
@vasuneet This can be easily found in package.json https://github.com/alexzuza/angular2-build-examples/blob/master/ngc-webpack/package.json#L12-L13
@alexzuza
value = `<span>Test interpolation {{5 + 6}}</span>`;
If using complex component containg attributes. That it will not work.
@Alekcei What do you mean? Try it https://github.com/alexzuza/angular2-build-examples/blob/master/ngc-webpack/src/app/app.component.ts#L10
@Alekcei I used your github project and had the same problem with the @Input decorator. I actually used a very simple workaround: instead of using @Input, I removed that entirely from the component and used 'inputs' instead.
So in your metadata, for example your button component, I would have:
let metaData = {
selector: 'ui-button',
template: `
<button type="button" class="button" [disabled]="disabled"><ng-content></ng-content></button>
`,
styleUrls: ['./button.component.less'],
inputs: [ 'disabled' ]
}
@Component(metaData)
@CustomComponent(metaData)
export class UiButtonComponent {
disabled: boolean = false;
}
@cybey Thank you! But I probably need to move to the webpack for prod build!
@alexzuza, Thanks for your posting. But still, I need to add my dynamic components in the shared.module.ts - how would I be able to change this during runtime ? For instance compiling components from an external resource ?
@Paladinium are you able to use AOT + JIT with Angular 5?
@p3x-robot : we're didn't upgrade yet and it will take a while because we're busy doing other stuff. So, I don't know.
@vasuneet I attached a ZIP to this issue a long time ago.
And to all the others: I had many discussion on this issue and provided a working example. I am glad if it works for you. If not, I don't care whether you think it works or not or whether it is using the JIT compiler in an AOT compiled app or not. Everything I knew about this topic is in my previous comments. From now on, I cannot provide any further help - sorry.
@Paladinium .. Are you using Jit Summaries for dynamic compilation of angular files at browser client? I am looking for a solution of resolving the angular application es5.js files at browser client using JIT Compiler. No success so far..
@alexzuza , when I add the case in my code, it throw errorNo NgModule metadata found for 'DynamicHtmlModule'. at NgModuleResolver.webpackJsonp.../../../compiler/esm5/compiler.js.NgModuleResolver.resolve
, but I see it has in section
const compMetadata = new Component({
selector: 'dynamic-html',
template: this.html,
});
app.module.ts section is
import { BrowserModule } from '@angular/platform-browser';
import { JitCompilerFactory } from '@angular/platform-browser-dynamic';
import { ChildComponent } from './child/child.component';
import { HtmlOutlet } from './child/html-outlet';
import { NgModule, Compiler, COMPILER_OPTIONS, CompilerFactory } from '@angular/core';
export function createCompiler(compilerFactory: CompilerFactory) {
return compilerFactory.createCompiler();
}
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent, ChildComponent, HtmlOutlet
],
imports: [
BrowserModule
],
providers: [
{provide: COMPILER_OPTIONS, useValue: {}, multi: true},
{provide: CompilerFactory, useClass: JitCompilerFactory, deps: [COMPILER_OPTIONS]},
{provide: Compiler, useFactory: createCompiler, deps: [CompilerFactory]}],
bootstrap: [AppComponent]
})
export class AppModule { }
package.json here
`["@angular/common": "^5.0.0",
"@angular/compiler": "^5.0.0",
"@angular/core": "^5.0.0",](url)
`
os: win10 nodejs 8.5.0 I add those in a small demo, it is ok, but it is failed when I add it to my project. Could you have a look? Thanks.
@Jackclarify ... https://github.com/angular/angular/issues/20639#issuecomment-348109570
You cannot use the ngtools package (with or without the CLI), they use optimizations that remove metadata when you compile AoT modules. If you want to lazy load a module AoT compiled, you have to compile it with ngc directly, not with ngtools, and then bundle it with rollup, webpack, system js bundler or closure compiler.
https://github.com/angular/angular/issues/20639#issuecomment-348109829
If you think that the CLI should take this use case into consideration and offer a way to bundle without removing those metadata (and I think that they should) then open an issue on the CLI repository please.
cli version 1.5.0. dont remove decorators
@Alekcei , thank you very much, it works. Thanks again, but we might not use if the latest version is not supported. I will appreciate that when cli will not remove decorators from now on.
And thanks @mlc-mlapis too.
@Jackclarify
Need to be angular cli, added a flag
@mlc-mlapis Dose it mean that aot and jit compile cannot work together right now, by using ngtools(angular/cli) only?
@Alekcei What do you mean? I'm not clear. And I'm sorry, I find I was wrong by using angular/cli v1.6.6, it can not work. :(
Guys, the CLI is removing the meta information that the JIT compiler needs. If you want this to be changed, I recommend that you upvote this CLI issue: https://github.com/angular/angular-cli/issues/9306
@Jackclarify ... I don't know anything that it is possible to use CLI 1.5.0 (as @Alekcei wrote here ... https://github.com/angular/angular/issues/15510#issuecomment-359837053).
I just know that there is an open issue https://github.com/angular/angular-cli/issues/9306 that is trying to solve the problem with removing the decorators.
We don't use NgTools / CLI so ... it doesn't affect us ... but I understand that it is a real problem for many others who use it.
I'm running into an issue with AOT + Lazy Loaded Modules + JIT @angular 5.1.2 @angular/cli 1.6.6 webpack 3.10.0
Using
new ngToolsWebpack.AngularCompilerPlugin({
tsConfigPath: helpers.root('tsconfig.json'),
entryModule: ...,
sourceMap: true
}),
If you try to run an app with the JIT Compiler:
export function createCompiler(compilerFactory: CompilerFactory) {
return compilerFactory.createCompiler();
}
[
{ provide: COMPILER_OPTIONS, useValue: {}, multi: true },
{ provide: CompilerFactory, useClass: JitCompilerFactory, deps: [COMPILER_OPTIONS] },
{ provide: Compiler, useFactory: createCompiler, deps: [CompilerFactory] },
]
the module loader looks for lazy.mod#LazyMod instead of lazy.mod.ngfactory#LazyModNgFactory (this works when not trying to use the JitCompiler). Manually updating those references to use lazy.mod.ngfactory#LazyModNgFactory then leaves you with
Error: No NgModule metadata found for '[object Object]'
where the object is LazyMod. I've modified the angular_compiler_plugin to not strip out decorators, and I can see the difference in the output (this is present only with the modification of keeping all decorators):
LazyMod = __decorate([
Object(__WEBPACK_IMPORTED_MODULE_0__angular_core__["K" /* NgModule */])({
imports: [...],
declarations: [...],
entryComponents: [...]
})
], LazyMod);
but I still see the same error. I don't think keeping the decorators is the only step required to fix this issue for Angular 5 + Lazy Loading + JIT. Any ideas as to what I could be missing? Any other details I can provide?
I can get a fully functioning app with lazy loading up and running (minus the ability to compile dynamic components), but adding the JIT Compiler breaks with the above issues.
@matt-duch ... SystemJsNgModuleLoader
or NgModuleFactoryLoader
detects if Angular compiler is available through DI. If yes, then it supposes that JIT module is wanted to be loaded ... so 'app/mymodule#MyModule'
loads mymodule.js
. If no, then it supposes that AOT module is wanted ... so 'mymodule.ngfactory.js'
is loaded automatically.
What I am missing is the reason why to lazy load JIT modules at all when the main reason why to use JIT compiling is the ability to get (or construct) any string which contains HTML template (from CMS for example) and compile it during run-time in a browser.
@mlc-mlapis Sorry for any confusion. Everything is AOT compiled (main app, and lazy loaded feature modules so all templates are inlined). They internally (in one place) make use of a component that renders tables dynamically based on database configurations. In order to provider a Compiler for that one component, I'm adding the JitCompilerFactory as seen in various threads around using JIT compiled dynamic components within AOT apps. If there's a better way to provider a JitCompiler for that component, I'd be happy to try. Or, is there a way to supply the JITCompiler as above, and tell the Loader to treat the lazy loaded modules as AOT anyways?
Separate from this, I attempted to create a JitCompiler under a const JitCompiler = new InjectionToken('JitCompiler')
, which the dynamic (JIT based) table component used instead of the default Compiler
injectable, but the directives it depends on (paging, loading helpers, etc) then JIT compiled using templateUrl, rather than using the already AOT compiled version present in the bundles.
Reply to the Comment
I am on Angular 4.3.3
I read the conversation above but failed to get the actual breakpoint or the fix. It would be really helpful if someone explains why it wasn't working for many and then as mentioned in the comment it worked by looking at the code shared.
Really Appreciate this discussion! Thank you.
Here is the stackoverflow question with the thing I have tried.
Render-html-element-stringwith-the-custom-directive-on-element-angular-4-3
Hi everyone, I convert the dynamic template module to a ng5 lib and it work, but I do not know why it is ok, is the reason that it export the decorators by NgxDynamicOutletModule? Can anyone help me? Thanks.
ngx-dynamic-outlet.umd.js: ` var NgxDynamicOutletModule = (function () { function NgxDynamicOutletModule() { }
NgxDynamicOutletModule.forRoot = function () {
return {
ngModule: NgxDynamicOutletModule,
};
};
NgxDynamicOutletModule.decorators = [
{ type: NgModule, args: [{
imports: [
CommonModule
],
declarations: [
HtmlOutlet
],
exports: [
HtmlOutlet
],
providers: [
{ provide: COMPILER_OPTIONS, useValue: ɵ0, multi: true },
{ provide: CompilerFactory, useClass: JitCompilerFactory, deps: [COMPILER_OPTIONS] },
{ provide: Compiler, useFactory: createCompiler, deps: [CompilerFactory] }
]
},] },
];
NgxDynamicOutletModule.ctorParameters = function () { return []; };
return NgxDynamicOutletModule;
}()); ` https://github.com/fresherchen/ngx-dynamic-outlet https://www.npmjs.com/package/ngx-dynamic-outlet
@Jackclarify ... do you mean the line export * from './html-outlet';
?
@mlc-mlapis thanks for your replay, I think it is not only for the line export * from './html-outlet';
, the compile tool (ng tool in my project, and ngc in the lib package) might be the real reason, I'm not sure, I will try to verify it.
There is an option, take a viewDef(html), and renderType(styles) from the factories created by the AOT compiler. At the same time, JIT will skip the compilation
@Jackclarify I've tried your repo located here, it works under a certern condition only, I use the code in the playgroud dir of the repo, it works, without or with -aot -prod
build option.
When I try a more complex scenario, and it doesn't work. I did the following things:
I added an angular components lib named jigsaw to the origin playgroud code, it looks like this after the modification:
content = `<a jigsaw-button (click)="showQuestion('fever chills normal')">
I have a fever/chills. Is this normal?
</a>`;
I add a directive provided by jigsaw named jigsaw-button
to the a
tag.
html-outlet
to the project, not imported them from node_modulesI did this because the origin html-outlet
code do not import jigsaw's module, I need to add the jigsaw's module to the dynamic module to be compiled to make sure the jigsaw-button
directive works correctly.
after these 2 steps, the code can be compiled, and, I get a runtime exception with -aot -prod
compile option:
ERROR Error: No NgModule metadata found for 'r'.
at t.resolve (vendor.e1e804e278036e05e784.bundle.js:1)
at t.getNgModuleMetadata (vendor.e1e804e278036e05e784.bundle.js:1)
at t._loadModules (vendor.e1e804e278036e05e784.bundle.js:1)
at t._compileModuleAndAllComponents (vendor.e1e804e278036e05e784.bundle.js:1)
at t.compileModuleAndAllComponentsAsync (vendor.e1e804e278036e05e784.bundle.js:1)
at t.compileModuleAndAllComponentsAsync (vendor.e1e804e278036e05e784.bundle.js:1)
at n.ngOnChanges (main.e2fa971268483487ba40.bundle.js:1)
at vendor.e1e804e278036e05e784.bundle.js:1
at vendor.e1e804e278036e05e784.bundle.js:1
at jo (vendor.e1e804e278036e05e784.bundle.js:1)
BTW, the modified code works without -prod -aot
compile option...
html-outlet
code, and it works againAfter a lot of retries, I think maybe the precompiled html-outlet
code in the node_modules could be the magic key, since I can not rebuild the repo by the way provided by the repo npm run build
, I started to hack the compiled html-outlet
code, I added the reference to jigsaw and add JigsawButtonModule
to the dynamic module's import array. After recompiled the testing app, I found it works!!
BUT Why??? anyone can help to answer the question?
@rdkmaster , unfortunately, my repo is inherited from ngx-dynamic-template. It can only achieve sample function, the directive/pipe will not work when importing to this module. The way might be work is that trying to implement the feature which directive/pipe did before importing to this module.
@IgorMinar @tbosch Any news about this issue? We are really in trouble because we have an application with a huge dynamic part that use JIT Compiler but have a startup delay (15 secs.). We need AOT to speedup the initial loading but we need also JIT Compiler!!! Please don't leave us alone... in the dark!
Is there any plan to support this?
Hi all,
Indeed, JIT and AOT in Angular with the View Engine runtime were independent - it wasn't really possible to mix and match the two. This was a systemic constraint, not a bug in the implementation.
The good news is that a major design goal for Angular Ivy was to support JIT/AOT interop. In Angular v9+ it's possible to build applications which are AOT compiled but consume dynamic, JIT-compiled components, or even the other way around if desired. There are still a few hiccups (#37216 for example) but overall the support is there.
Thank you @alxhub. Just like you said Angular9 works fine for us in AOT mode with some JIT dynamic components. The only issue left is devkit/terser optimizations during AOT builds.
In Angular v9+ it's possible to build applications which are AOT compiled but consume dynamic, JIT-compiled components, or even the other way around if desired.
@alxhub : I couldn't find any example of this. Can you point me in right direction ?
Hi all,
AOT+JIT interop with any build optimizations is not a supported path and we don't recommend this approach to be used for production. The main reasons are that this approach increases drastically the bundle sizes, performance overhead and exposes your application to cross-site scripting (XSS) since compiling components at runtime is a XSS vulnerability in itself.
I created an issue to capture and document this: https://github.com/angular/angular/issues/39624
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.
I'm submitting a ... (check one with "x")
Current behavior Since 4.0.0,
JitCompiler
cannot be used with AoT compilation. It's exported from@angular/compiler
but its compiled import path is@angular/compiler/src/jit/compiler
app.module.ts
app.module.ngfactory.ts(summary)
@angular/compiler/src/jit/compiler
is not existing JS file (because of 4.0.0 FESM). webpack bundling crashes by this problem.Expected behavior
Resolve
JitCompiler
from@angular/compiler
Minimal reproduction of the problem with instructions
https://github.com/laco0416/ngrepro-0001
What is the motivation / use case for changing the behavior?
Please tell us about your environment: OSX
Angular version: 4.0.0
Language: TypeScript 2.2
Node (for AoT issues):
node --version
= 6.9.5