Yan*_*git 9 jit aot angular angular-aot angular5
在angular5上,我尝试对我的大多数模块/组件进行相同的项目AOT编译......但我有一部分需要进行JIT编译.
对于第二部分,HTML来自Ajax请求并包含一些必须由angular编译的组件标记.要管理这部分,我使用看起来像这样的指令:
export class ArticleLiveDirective implements OnInit, OnChanges, OnDestroy {
// [...]
constructor(
private container: ViewContainerRef,
private compiler: Compiler
) { }
// [...]
private addHtmlComponent(template: string, properties: any = {}) {
this.container.clear();
//Force always rootDomElement.
const divTag = document.createElement('div');
divTag.setAttribute('id',this.currentId);
divTag.innerHTML = template;
template = divTag.outerHTML;
// We create dynamic component with injected template
@Component({ template })
class ArticleLIveComponent implements OnInit, OnChanges, OnDestroy {
constructor(
private articleService: ArticleService
) {}
ngOnInit() {}
ngOnChanges(changes: SimpleChanges) {}
ngOnDestroy() {}
goToPage($event: Event, pagination: string) {
this.articleService.askToChangeArticle(pagination);
//Stop propagation
$event.stopPropagation();
return false;
}
}
// we declare module with all dependencies
@NgModule({
declarations: [
ArticleLIveComponent
],
imports: [
BrowserModule,
MatTabsModule
],
providers: []
})
class ArticleLiveModule {}
// we compile it
const mod = this.compiler.compileModuleAndAllComponentsSync(ArticleLiveModule);
const factory = mod.componentFactories.find((comp) =>
comp.componentType === ArticleLIveComponent
);
// fetch instance of fresh crafted component
const component = this.container.createComponent(factory);
// we inject parameter.
Object.assign(component.instance, properties);
}
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,我可以使用自定义HTML作为模板调用addHtmlComponent方法在运行时编译新组件.
我的模板看起来像:
<div>
<h2>Foo bar</h2>
<mat-tab-group>
<mat-tab label="Tab 1">Content 1</mat-tab>
<mat-tab label="Tab 2">Content 2</mat-tab>
</mat-tab-group>
<p>Other content</p>
Run Code Online (Sandbox Code Playgroud)
一切顺利,直到我切换到AOT编译(我使用:https://github.com/angular/angular-cli/tree/master/packages/%40ngtools/webpack)
可能的原因: 我猜的主要原因是因为AOT编译从输出编译的bundle中删除Angular的"编译器"部分. 我尝试了什么 - 我试图直接在我的代码上要求它但仍然不存在. - 我试着检查像角度(或角度材料)的网站如何处理它.但是不符合我的情况.实际上,两者都已经在AOT版本中编译了所有示例的版本.动态部分是样本周围的"正义"内容.
如果你想检查角度材料是如何做的:每个组件的所有网站示例:https://github.com/angular/material2/tree/master/src/material-examples
然后他们有装载机:https: //github.com/angular/material.angular.io/blob/master/src/app/shared/doc-viewer/doc-viewer.ts#L85
可能是正确的方法,但我不知道如何适应它来管理,动态Tab内容.
编辑:我在这里添加样本:https://github.com/yanis-git/aot-jit-angular(branch Master)
正如您将看到的,AOT编译从bundle中删除了wall编译器,结果如下:
Module not found: Error: Can't resolve '@angular/compiler/src/config'
Run Code Online (Sandbox Code Playgroud)
我试图在AppModule上强制使用compilater Factory,但仍然没有结果.
我在同一个repo上有另一个示例,但是在分支"lazy-jit"上,现在我将Compiler嵌入到输出的包中,但是新的错误出现在我面前:
ERROR Error: No NgModule metadata found for 'ArticleLiveModule'.
Run Code Online (Sandbox Code Playgroud)
谁看起来与这个问题完全相同:https://github.com/angular/angular/issues/16033
试试这个:
import { Compiler, COMPILER_OPTIONS, CompilerFactory, NgModule } from '@angular/core';
import { BrowserModule, } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { AppComponent } from './app.component';
import { HelloComponent } from './hello.component';
import { JitCompilerFactory } from '@angular/platform-browser-dynamic';
export function createCompiler(compilerFactory: CompilerFactory) {
return compilerFactory.createCompiler();
}
@NgModule({
providers: [
{ provide: COMPILER_OPTIONS, useValue: {}, multi: true },
{ provide: CompilerFactory, useClass: JitCompilerFactory, deps: [COMPILER_OPTIONS] },
{ provide: Compiler, useFactory: createCompiler, deps: [CompilerFactory] }
],
imports: [BrowserModule, FormsModule],
declarations: [AppComponent, HelloComponent],
bootstrap: [AppComponent]
})
export class AppModule { }
Run Code Online (Sandbox Code Playgroud)
但是JitCompiler仍然无法创建依赖注入树.我怀疑@Injectable是从AOT部分删除的.但我不能做你的伎俩.
在上面的代码示例中,没有用于NgModule和Component的装饰器.所以,这意味着没有@Injectable也无法注入providers.那么为什么我们不为@NgModule和@Component @Injectable装饰器编写并只将其写入服务?因为,他们有一个装饰器(@ NgModule/@ Components),Services而不是.他们的装饰者足以让Angular知道他们是可注射的.
带DI的代码示例.
更新:
创建定制的包装CustomNgModule,CustomComponent和CustomInjectable装饰:
export function CustomComponent(annotation: any) {
return function (target: Function) {
const component = new Component(annotation);
Component(component)(target);
};
}
export function CustomNgModule(annotation: any) {
return function (target: Function) {
const ngModule = new NgModule(annotation);
NgModule(ngModule)(target);
};
}
export function CustomInjectable() {
return function (target: Function) {
const injectable = new Injectable();
Injectable()(target);
};
}
Run Code Online (Sandbox Code Playgroud)
使用
AOTflag 构建时,Angular-CLI看起来像是从需要动态编译的代码部分中清除本机装饰器的包.如果您希望
dynamically使用AOT具有DI功能的组件编译模块,请将原始装饰器(NgModule/Injectable...)替换为自定义装饰器以在AOT编译模式下保留装饰器 :
lazy.module.ts:
@CustomComponent({
selector: 'lazy-component',
template: 'Lazy-loaded component. name: {{name}}.Service
{{service.foo()}}!',
//providers: [SampleService]
})
export class LazyComponent {
name;
constructor(public service: SampleService) {
console.log(service);
console.log(service.foo());
}
}
@CustomNgModule({
declarations: [LazyComponent],
providers: [SampleService]
})
export class LazyModule {
}
Run Code Online (Sandbox Code Playgroud)
app.component.ts:
...
ngAfterViewInit() {
this.compiler.compileModuleAndAllComponentsAsync(LazyModule)
.then((factories) => {
const f = factories.componentFactories[0];
const cmpRef = this.vc.createComponent(f);
cmpRef.instance.name = 'dynamic';
});
}
...
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1903 次 |
| 最近记录: |