Angular2 (CLI) 树抖动删除动态创建的 NgModule [英] Angular2 (CLI) tree shaking removing dynamically created NgModule

查看:25
本文介绍了Angular2 (CLI) 树抖动删除动态创建的 NgModule的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 Angular-cli tree-shaking 排除组件中假设了这个问题from去除非常相似,但我似乎无法从中得到任何东西.

I assume the question at Angular-cli tree-shaking exclude component from removal is very similar but I can't seem to get anything out of it.

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

Essentially I have a dynamic component factory as described in How can I use/create dynamic template to compile dynamic Component with Angular 2.0?.

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

When I build it using the latest Angular CLI with a non-production setting, it all works fine. However, once I use the production setting I get the following error trace in the browser immediately when trying to load a page that has dynamically created content:

例外:未找到e"的 NgModule 元数据.
原始堆栈跟踪:
main.dc05ae9....bundle.js:formatted:4731
错误:没有 NgModule 元数据找到e".
在 f (vendor.c18e6df....bundle.js:formatted:76051)
在 t.resolve (vendor.c18e6df....bundle.js:formatted:20624)
在 t.getNgModuleMetadata (vendor.c18e6df....bundle.js:formatted:20169)
在 t._loadModules (vendor.c18e6df....bundle.js:formatted:40474)
在 t._compileModuleAndAllComponents (vendor.c18e6df....bundle.js:formatted:40462)
在 t.compileModuleAndAllComponentsSync (vendor.c18e6df....bundle.js:formatted:40436)
在 e.createComponentFactory (main.dc05ae9….bundle.js:formatted:4789)

EXCEPTION: No NgModule metadata found for 'e'.
ORIGINAL STACKTRACE:
main.dc05ae9….bundle.js:formatted:4731
Error: No NgModule metadata found for 'e'.
at f (vendor.c18e6df….bundle.js:formatted:76051)
at t.resolve (vendor.c18e6df….bundle.js:formatted:20624)
at t.getNgModuleMetadata (vendor.c18e6df….bundle.js:formatted:20169)
at t._loadModules (vendor.c18e6df….bundle.js:formatted:40474)
at t._compileModuleAndAllComponents (vendor.c18e6df….bundle.js:formatted:40462)
at t.compileModuleAndAllComponentsSync (vendor.c18e6df….bundle.js:formatted:40436)
at e.createComponentFactory (main.dc05ae9….bundle.js:formatted: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' 是 createComponentModule 中的函数 e(),如您所见,它是空的,即使它应该包含 @NgModule 内容.

The 'e' in the error message is the function e() from createComponentModule which, as you can see, is empty even though is should contain the @NgModule content.

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

How can I create a new NgModule dynamically and still use the production mode of Angular CLI?

版本:
Angular2:2.4.8
角 CLI:1.0.0-beta.32.3
打字稿:2.1.6

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

推荐答案

我有同样的错误信息.我发现的解决方法是不对运行时模块使用装饰器.

I have the same error message. The workaround I found is not to use the decorator for the runtime module.

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 中模块的元数据通常被声明为装饰器.

Okay, I did not fully understand why the error occurs. The error message basically says that module e does not have metadata. Metadata of a module in Angular is usually declared as decorator.

ES7 中的装饰器相当于咖喱函数.这意味着

Decorators in ES7 are equivalent to curry functions. It means

@NgModule({})
class A {}

等于

NgModule({})(class A {})

我个人认为咖喱的方式要好得多...

Personally I think the curry way is much better...

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

Updated 22 Match: The answer from official repo https://github.com/angular/angular-cli/issues/5359#issuecomment-287500703 is simply not using AOT. Please build the code with ng build --prod --no-aot In my case, everything is solved.

这篇关于Angular2 (CLI) 树抖动删除动态创建的 NgModule的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆