我认为Angular-cli tree-shaking exclude component from removal的问题非常相似,但我似乎无法从中得到任何结论。
基本上我有一个动态组件工厂,如How can I use/create dynamic template to compile dynamic Component with Angular 2.0?中所述。
当我使用最新的Angular CLI和非生产设置构建它时,一切正常。但是,一旦我使用生产设置,我在尝试加载具有动态创建内容的页面时会立即在浏览器中获得以下错误跟踪:
例外:找不到'e'的NgModule元数据。
原始STACKTRACE:
main.dc05ae9 ... .bundle.js:格式:4731左错误:没有NgModule元数据 找到'e'。
在f(vendor.c18e6df ... .bundle.js:格式:76051)
在t.resolve(vendor.c18e6df ... .bundle.js:格式:20624)
在t.getNgModuleMetadata(vendor.c18e6df ... .bundle.js:格式:20169)
在t._loadModules(vendor.c18e6df ... .bundle.js:格式:40474)
在t._compileModuleAndAllComponents(vendor.c18e6df ... .bundle.js:格式:40462)
在t.compileModuleAndAllComponentsSync(vendor.c18e6df ... .bundle.js:格式:40436)
在e.createComponentFactory(main.dc05ae9 ... .bundle.js:格式:4789)
这是我的组件工厂类:
@Injectable()
export class DynamicTypeBuilder {
constructor() {
}
private _cacheOfFactories: {[templateKey: string]: ComponentFactory<any>} = {};
private compiler: Compiler = new JitCompilerFactory([{useDebug: false, useJit: true}]).createCompiler();
public createComponentFactory<COMPONENT_TYPE>(type: any, template: string, additionalModules: any[] = []): Observable<ComponentFactory<COMPONENT_TYPE>> {
let factory = this._cacheOfFactories[template];
if (factory) {
return Observable.of(factory);
}
// unknown template ... let's create a Type for it
let module = this.createComponentModule(type, additionalModules);
// compiles and adds the created factory to the cache
return Observable.of(this.compiler.compileModuleAndAllComponentsSync(module))
.map((moduleWithFactories: ModuleWithComponentFactories<COMPONENT_TYPE>) => {
factory = moduleWithFactories.componentFactories.find(value => value.componentType == type);
this._cacheOfFactories[template] = factory;
return factory;
});
}
protected createComponentModule(componentType: any, additionalModules: any[]): Type<any> {
@NgModule({
imports: [
FormsModule,
ReactiveFormsModule,
BrowserModule,
PipesModule,
...additionalModules
],
declarations: [
componentType
],
schemas:[CUSTOM_ELEMENTS_SCHEMA]
})
class RuntimeComponentModule {
}
return RuntimeComponentModule;
}
}
正在被翻译成
var _ = function() {
function e() {
this._cacheOfFactories = {},
this.compiler = new i.a([{
useDebug: !1,
useJit: !0
}]).createCompiler()
}
return e.prototype.createComponentFactory = function(e, t, n) {
var i = this;
var _ = this._cacheOfFactories[t];
if (_)
r.Observable.of(_);
var a = this.createComponentModule(e, n);
return r.Observable.of(this.compiler.compileModuleAndAllComponentsSync(a)).map(function(n) {
return _ = n.componentFactories.find(function(t) {
return t.componentType == e
}),
i._cacheOfFactories[t] = _,
_
})
}
,
e.prototype.createComponentModule = function(e, t) {
var n = function() {
function e() {}
return e
}();
return n
}
,
e.ctorParameters = function() {
return []
}
,
e
}()
错误消息中的“e”是来自e()
的{{1}}函数,正如您所看到的那样,它是空的,即使它应该包含createComponentModule
内容。
如何动态创建新的NgModule并仍然使用Angular CLI的生产模式?
版本:
Angular2:2.4.8
Angular CLI:1.0.0-beta.32.3
TypeScript:2.1.6
答案 0 :(得分:0)
我有相同的错误消息。我发现的解决方法是不要将装饰器用于运行时模块。
protected createComponentModule(componentType: any, additionalModules: any[]): Type<any> {
return NgModule({
imports: [
FormsModule,
ReactiveFormsModule,
BrowserModule,
PipesModule,
...additionalModules
],
declarations: [
componentType
],
schemas:[CUSTOM_ELEMENTS_SCHEMA]
})(class RuntimeComponentModule {});
}
好的,我没有完全理解错误发生的原因。错误消息基本上表示模块e
没有元数据。 Angular中模块的元数据通常被声明为装饰器。
ES7中的装饰器相当于咖喱功能。这意味着
@NgModule({})
class A {}
等于
NgModule({})(class A {})
我个人认为咖喱方式好多了......
更新了22匹配:
官方报告的回答https://github.com/angular/angular-cli/issues/5359#issuecomment-287500703
根本就没有使用AOT。
请使用ng build --prod --no-aot
构建代码
在我的情况下,一切都解决了。
答案 1 :(得分:0)
不幸的是,目前看来这是不可能的(我会尽力保持最新的答案),无论是Angular 2.x还是Angular 4 beta。
问题是动态组件定义包含文件引用(模板,样式表),这些文件引用在运行时无法通过之前运行的AOT编译器解析。
但是,如果组件或模块不包含文件引用,则当前的Angular代码不允许真正动态创建组件。它只是找不到在运行时创建的元数据。
总结问题,有3个级别的动态组件创建:
在我看来,第二个问题可以解决。 Angular团队说,因为它是AOT,它只能编译那些在AOT编译时静态知道的东西,但我不同意。
我可以想到AOT编译这样一个组件的“存根”的可能性,然后在需要时用动态模板或样式表进行实例化。可能需要为@Component
注释使用新属性或像@DynamicComponent
使用全新注释,但对我来说似乎是可行的。我不知道@NgModule
声明是否需要进行相同的更改,但我认为他们会这样做。