2017-03-01 9 views
11

Angular-cli tree-shaking exclude component from removal에 대한 질문은 매우 유사하다고 생각되지만 그 중 아무 것도 얻을 수없는 것으로 보입니다.동적으로 생성 된 NgModule을 제거하는 Angular2 (CLI) 트리

기본적으로 나는 How can I use/create dynamic template to compile dynamic Component with Angular 2.0?에서 설명한 동적 구성 요소 팩토리를 가지고 있습니다.

비 생산 설정으로 최신 Angular CLI를 사용하여 빌드하면 모든 것이 올바르게 작동합니다.

@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; 
    } 
} 
: 여기

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)

내 부품 공장 클래스입니다 : 내가 생산 설정을 사용하면 동적으로 컨텐츠 생성 한 페이지를로드 할 때, 나는 즉시 브라우저에서 다음과 같은 오류 추적을 얻을

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

오류 메시지의 '예'로되고 transpiled

createComponentModule WHI에서 함수이다 e() ch는 (볼 수 있듯이) @NgModule 콘텐츠가 포함되어 있어도 비어 있습니다.

어떻게 새로운 NgModule을 동적으로 생성하고 Angular CLI의 생산 모드를 사용할 수 있습니까?

버전 :
Angular2 : 2.4.8
각도 CLI : 1.0.0-beta.32.3
타이프 : 2.1.6

답변

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 일치 의미 공식의 repo에서 대답 https://github.com/angular/angular-cli/issues/5359#issuecomment-287500703 입니다 단순히 AOT를 사용하지 마십시오. 코드를 작성하십시오 ng build --prod --no-aot 제 경우에는 모든 것이 해결되었습니다.

+0

제대로 작동하지 않을 까봐 걱정됩니다. 코드가 잘 컴파일되고 이동 된 JS에 포함되어 있지만 이제는 새로운 문제가 있습니다. Angular는 새'NgModule'에서 가져온 사용자 정의 모듈을 찾을 수 없습니다. 그래서 위의 예제에서'FormsModule','ReactiveFormsModule'과'BrowserModule'을 찾을 수 있습니다 만,'PipesModule'은 찾을 수 없습니다. 오류는'CompileMetadataResolver.getNgModuleMetadata'에 있습니다. – Sebastian

+0

실제로 동일한 문제가 발생합니다. JIT 컴파일에서 데코레이터를 전혀 컴파일하지 않는 것 같습니다. 뿐만 아니라'RuntimeComponentModule'. 컴파일 된'main.js'를 읽었을 때'PipesModule'에 대한 메타 데이터를 포함하고 있지 않습니다. 나는이 시간에 계속할 것이다. 각도 모듈이 괜찮다는 것을 알려준 Thx. –

+0

지금 당장 jit + aot를 사용하고 있습니다. v4에서 –

0

안타깝게도 Angular 2.x 나 Angular 4 베타 중 어느 것도이 순간에는 불가능합니다 (답변을 최신 상태로 유지하려고합니다).
동적 구성 요소 정의에 이전에 실행 된 AOT 컴파일러로 런타임에 더 이상 해결할 수없는 파일 참조 (템플리트, 스타일 시트)가 포함되어 있다는 점이 문제점입니다.
그러나 구성 요소 또는 모듈에 파일 참조가 포함되어 있지 않은 경우 현재 Angular 코드는 구성 요소의 진정한 동적 생성을 허용하지 않습니다. 단지 런타임에 생성되는 메타 데이터를 찾지 못합니다.

  1. 정적 구성 요소를 정의하고 그것이 AOT 컴파일러는 컴파일 시간 AOT에서 찾을 수 있다는 NgModule에 포함 :

    문제를 요약, 동적 요소 생성의 3 단계가있다. 이러한 구성 요소는 언제든지 문제없이 인스턴스화 할 수 있습니다. (ComponentFactoryResolver 등 참조)

  2. 구성 요소의 본문을 정적으로 (코드 등) 정의하지만 동적 템플릿 및/또는 스타일을 허용합니다. 즉, 필요할 때만 템플릿에 템플릿이 만들어집니다. 또한 런타임시 NgModule을 컴파일해야합니다. 이것은 현재 AOT 컴파일러를 사용하지 않을 때만 가능하며 여기에 게시 한 문제점을 나타냅니다.
  3. 코드 및 템플릿을 포함하여 전체 구성 요소를 동적으로 정의하십시오. 이것은 여기에 의도 된 것이 아니며 멀리까지 갈 수도 있습니다. 그러나 아마도 누군가이 문제를 가지고있을 수도 있습니다.

제 생각에는 2 번 문제를 해결할 수 있습니다. Angular 팀은 AOT이므로 AOT 컴파일 타임에 정적으로 알려진 것들만 컴파일 할 수 있다고 말합니다. 그러나 동의하지 않습니다.
필자는 AOT가 필요할 때 동적 템플릿 또는 스타일 시트로 인스턴스화되는 이러한 구성 요소의 '스텁'을 컴파일 할 수있는 가능성을 생각할 수 있습니다. @Component 주석을위한 새로운 속성이나 @DynamicComponent과 같은 완전히 새로운 주석을 사용해야 할 필요가 있을지 모르지만, 나에게 실현 가능성이 있습니다. @NgModule 선언에 대해 동일한 변경이 필요한지는 알 수 없습니다.

+0

을 사용하고 있습니다. jit + aot 한번에 :) –

+0

그래, github에 스레드를 보았다! 이제 CLI에서 작동하도록해야합니다. – Sebastian

+0

ciao Sebastian! –