Angular 6/7 AOT:动态模板渲染 - 为模块加载 JitCompiler
Posted
技术标签:
【中文标题】Angular 6/7 AOT:动态模板渲染 - 为模块加载 JitCompiler【英文标题】:Angular 6/7 AOT: Dynamic template render - load JitCompiler for module 【发布时间】:2019-05-21 00:29:02 【问题描述】:我在从 API 响应“即时”构建模板时遇到问题,但仅限于 AoT 构建。
我从后端收到这样的回复:
<h1>Title...</h1>
<some-component></some-componen>
<p>other content</p>
我想像普通的 Angular 模板一样解析它。
我的组件的简化代码如下所示:
import
Compiler,
Component,
ComponentFactory,
ComponentRef,
Injector,
Input,
NgModule,
OnChanges,
OnDestroy,
OnInit,
ViewContainerRef
from '@angular/core';
import CommonModule from '@angular/common';
import RouterModule from '@angular/router';
export async function createComponentFactory(compiler: Compiler, metadata: Component): Promise>
const cmpClass = class DynamicComponent
;
const decoratedCmp = Component(metadata)(cmpClass);
// IMPORT ALL MODULES HERE!!!
@NgModule(imports: [CommonModule, RouterModule], declarations: [decoratedCmp])
class DynamichtmlModule
const moduleWithComponentFactory = await compiler.compileModuleAndAllComponentsAsync(DynamicHtmlModule);
return moduleWithComponentFactory.componentFactories.find(x => x.componentType === decoratedCmp);
@Component(
selector: 'html-renderer',
templateUrl: './html-renderer.component.html',
styleUrls: ['./html-renderer.component.scss']
)
export class HtmlRendererComponent implements OnInit, OnChanges, OnDestroy
@Input() content: string;
cmpRef: ComponentRef;
constructor(private vcRef: ViewContainerRef, private compiler: Compiler)
ngOnInit(): void
console.log('init...')
console.log(this.compiler)
ngOnDestroy()
if (this.cmpRef)
this.cmpRef.destroy();
ngOnChanges()
const html = this.content;
if (!html) return;
if (this.cmpRef)
this.cmpRef.destroy();
const compMetadata = new Component(
selector: 'dynamic-selector',
template: this.content,
);
createComponentFactory(this.compiler, compMetadata)
.then(factory =>
const injector = Injector.create(providers: [], parent: this.vcRef.injector);
this.cmpRef = this.vcRef.createComponent(factory, 0, injector, []);
);
所以,我将整个数据传入content
输入,然后通过compileModuleAndAllComponentsAsync
方法(https://angular.io/api/core/Compiler#compilemoduleandallcomponentssync)编译所有组件
并且所有工作都在 JIT 构建中运行。
我想在 AoT 编译中完成这项工作,因为现在我收到一个错误:
Runtime Compiler is not loaded
在示例代码上使用 AoT 构建时
我也尝试在providers[]
的 app.module.ts 中提供编译器,但它也不起作用:
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],
我的问题:有没有办法将延迟加载的模块包含在 JIT 编译器中以访问其方法?
我找到了一些相关的问题,但没有答案:
Error while using @angular compiler in Angular 5 and AOT-Build
编辑 15.01.2019 这是 stackblitz.com 上的一个有效 JIT 示例,其中包含插值和数据绑定测试: https://stackblitz.com/github/lyczos/angular-dynamic-html-renderer
编辑 05.01.2020 目前,我已经开始使用builder.io Steve(该项目的作者)正在使用 Web 组件来使其工作。
【问题讨论】:
其实我觉得这是个好问题。对我来说看起来不错! :) 让我改述一下:您想在不加载编译器的情况下使用编译器。很抱歉,这里有一个逻辑问题……您要么使用 JIT(带编译器)或 AOT(不带编译器)。 @Hatef 这怎么可能是个好问题? @smnbbrv 对,但是有什么方法可以将编译器(即时)附加到延迟加载的模块上,以免增加初始应用程序加载时间?例如我在这里看到了这个,但它不适用于 Angular 6/7 github.com/alexzuza/angular2-build-examples/tree/master/… @smnbbrv 好的,知道了。您是否看到任何其他可能的解决方案/想法来“即时”构建模板? @smnbbrv 它的格式很好,包含了经过尝试的代码,添加了相关问题的链接,绝对是关于主题的,他们的问题很明确 - 如果 OP 的逻辑/他们试图做的事情没有对您/我们来说没有意义,这并不是一个坏问题。 【参考方案1】:首先,我很抱歉写这个作为答案,但它太长了,不能作为评论。
可以按照您的要求进行操作。事实上,我实际上在今年的 ng-conf 上提出了这个确切的问题。在 Max Koretskyi(又名 angularindepth.com 的“ng-wizard”作者)就这个主题进行了一次会议后,我与他进行了交谈。
我必须警告你,尽管他提供的解决方案非常复杂、笨拙,而且你不能指望它不会在未来的 Angular 版本中破坏,因为你试图完成的事情违背了 Angular 框架,而这正是Angular 团队正试图阻止人们这样做。真的,试图维护它只是一场噩梦,任何新的开发者都可能会弹出他们的顶峰,试图理解我所做的事情。哎呀,如果我一年多后回顾它,我什至可能都不知道我做了什么。
最终,我决定放弃 AOT 并使用 JIT 部署我的应用程序,从那以后我没有后悔我的决定。如果你决定你真的想进一步追求这个,我建议你联系 Max。从我在 ng-conf 收集到的信息来看,他是一个非常友好的人,如果他们有问题,他会公开邀请人们与他联系。希望对您有所帮助,祝您好运! :)
【讨论】:
我有工作解决方案 :) 看看@Narm : builder.io【参考方案2】:我去年遇到了同样的问题,并且能够找到解决方法。我在样式指南中使用了动态生成的角度组件。这是一个适用于 AOT 编译的工作示例:
https://github.com/johncrim/angular-dynamic-styleguide
将import 'core-js/es7/reflect';
添加到polyfills.ts
是关键的非显而易见的技巧。
使用ng build --prod
运行动态编译的组件也需要
"buildOptimizer": false,
在 angular.json 中的生产配置中。请注意,关闭 buildOptimizer 可能会增加您的包大小,但至少您将获得预编译大部分代码的好处。
【讨论】:
1.是否可以在 aot :D 和 2 中延迟加载 jit 编译器。我们如何“动态”执行连接到 templateHTML 的 js/ts(装饰组件类)?以上是关于Angular 6/7 AOT:动态模板渲染 - 为模块加载 JitCompiler的主要内容,如果未能解决你的问题,请参考以下文章
为啥即使模板访问私有属性,Angular AOT 也会编译?