Angular2(CLI)树抖动动态创建的NgModule

Seb*_*ian 14 webpack angular-cli tree-shaking angular

我认为在Angular-cli树抖动中排除组件的问题非常相似,但我似乎无法从中得到任何东西.

基本上我有一个动态组件工厂,如我如何使用/创建动态模板来编译动态组件与Angular 2.0?.

当我使用最新的Angular CLI和非生产设置构建它时,一切正常.但是,一旦我使用生产设置,我在尝试加载具有动态创建内容的页面时立即在浏览器中获得以下错误跟踪:

例外:找不到'e'的NgModule元数据.
ORIGINAL STACKTRACE:
main.dc05ae9 ... .bundle.js:格式:4731
错误:找不到'e'的NgModule元数据.
at t(vendor.c18e6df ... .bundle.js:格式化:76051)
at t.resolve(vendor.c18e6df ... .bundle.js:格式化:20624)
at t.getNgModuleMetadata(vendor.c18e6df ... .bundle.js:formatted: 20169)
在t._compileModuleAndAllComponents(vendor.c18e6df ... .bundle.js:格式化:40462)的t._loadModules(vendor.c18e6df ... .bundle.js:格式化:40474
)
at 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;
  }
}
Run Code Online (Sandbox Code Playgroud)

正在被转化为

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
}()
Run Code Online (Sandbox Code Playgroud)

在"E"错误消息是功能e()createComponentModule,正如你所看到的,是空的即使应该包含的@NgModule内容.

如何动态创建新的NgModule并仍然使用Angular CLI的生产模式?

版本:
Angular2:2.4.8
Angular CLI:1.0.0-beta.32.3
TypeScript:2.1.6

Ant*_*ang 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 {});
}
Run Code Online (Sandbox Code Playgroud)

好吧,我没有完全理解为什么会出现错误。错误消息基本上表明该模块e没有元数据。Angular 中模块的元数据通常被声明为装饰器。

ES7 中的装饰器相当于柯里化函数。它的意思是

@NgModule({})
class A {}
Run Code Online (Sandbox Code Playgroud)

等于

NgModule({})(class A {})
Run Code Online (Sandbox Code Playgroud)

个人觉得咖喱的做法比较好...

更新了 22 场比赛:官方仓库https://github.com/angular/angular-cli/issues/5359#issuecomment-287500703 的答案 就是不使用 AOT。请使用 构建代码ng build --prod --no-aot 在我的例子中,一切都解决了。