gpt4 book ai didi

同一个项目中的 Angular AOT 和 JIT

转载 作者:太空狗 更新时间:2023-10-29 17:10:11 25 4
gpt4 key购买 nike

在 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);
}
}

如您所见,我可以调用 addHtmlComponent 方法在运行时使用自定义 HTML 作为模板编译新组件。

我的模板看起来像:

<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>

一切正常,直到我切换到 AOT 编译(仅供引用:https://github.com/angular/angular-cli/tree/master/packages/%40ngtools/webpack)

可能的原因:我猜的主要原因是因为 AOT 编译从输出编译包中删除了 Angular 的“编译器”部分。我尝试过的 - 我已经尝试直接在我的代码中要求它,但仍然不存在。 - 我已经尝试检查像 Angular (或 Angular Material )这样的网站如何处理它。但不适合我的情况。事实上,两者都已经在AOT版本中编译了所有示例的版本。动态部分“只是”样本周围的内容。

如果你想检查 Angular Material 是如何做到的:每个组件的所有网站示例: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

这可能是正确的方法,但我不知道如何调整它来管理动态标签内容。


编辑:我在这里添加示例:https://github.com/yanis-git/aot-jit-angular (科长)

正如你将看到的,AOT 编译从 bundle 中移除了 wall compiler,这个结果:

Module not found: Error: Can't resolve '@angular/compiler/src/config'

我已经尝试在 AppModule 上强制编译工厂,但仍然没有结果。

我在同一个 repo 上有另一个示例,但是在分支“lazy-jit”上,现在我在输出的包中嵌入了编译器,但是我遇到了新的错误:

ERROR Error: No NgModule metadata found for 'ArticleLiveModule'.

谁看起来和这个问题一模一样: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 { }

CODE EXAMPLE

But JitCompiler still not able to create Dependency Injection tree. I suspect @Injectable to be remove from AOT part. But i can't do your trick.

在上面的代码示例中,NgModule 和 Component 没有装饰器。所以,这意味着也没有@Injectable,他们不能注入(inject)providers。那么为什么我们不为 @NgModule@Component 编写 @Injectable 装饰器,而只将其写入 Services ?因为,他们有装饰器(@NgModule/@Components),Services 没有。并且它们的装饰器足以让 Angular 知道它们是可注入(inject)的

CODE EXAMPLE与 DI。

更新:创建了自定义包装器 CustomNgModuleCustomComponentCustomInjectable 装饰器:

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);
};
}

When building with AOT flag, Angular-CLI looks like cleans bundle from native decorators from parts of code which need to be compiled dynamically.

And where you want dynamically compile modules with components in AOT with DI functionality, replace native decorators (NgModule/Injectable...) with custom one to preserve decorators in AOT compilation mode:

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 {
}

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';
});
}
...

CODE EXAMPLE 3

关于同一个项目中的 Angular AOT 和 JIT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49249919/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com