2017-09-15 16 views
0

typescript 2.4 [import()][1]功能幫助動態加載模塊。我已經嘗試過這個功能,而且效果很好。無論何時寫入腳本並且導入的模塊位於同一文件夾中,我都能夠動態地將模塊和組件加載到一起。如何導入外部模塊或插件動態使用typescript 2.4的import()功能在Angular CLI生成腳本中生成腳本

當我試圖在生產模式中構建它時,問題就開始了。我正在使用Angular-CLI並在生產模式下構建我的項目,並生成javascript捆綁包。現在我很困惑加載模塊。

我正在開發一個基於插件的功能,可以動態添加不同的插件。所以,這些插件與主應用程序分離,可以使用import()方法動態添加。在開始時,我開發了打字稿中的插件,並且這些插件使用import()方法完美加載。但在生產模式下,插件應該是javascript庫,可以使用import()方法導入。

因此,我使用https://github.com/jvandemo/generator-angular2-library將插件轉換爲庫。並試圖導入index.js文件。但它給出了一個錯誤信息"ERROR Error: Uncaught (in promise): Error: No NgModule metadata found for 'undefined'."

下面的代碼我用來動態地導入模塊和組件。

export class DynamicComponent {  
     injector: Injector; 
     compiler: Compiler; 
     @ViewChild('container', {read: ViewContainerRef}) 
     container: ViewContainerRef; 
     componentRef: any; 

     constructor(private compFactoryResolver: ComponentFactoryResolver, injector: Injector, 
      private apiService: apiService) { 

      this.injector = ReflectiveInjector.resolveAndCreate(COMPILER_PROVIDERS, injector); 
      this.compiler = this.injector.get(Compiler); 
     } 
     addWidget(){ 

      apiService.getMoudleUrls().subscribe(module_url=>{ 
      let module_= import(module_url); //e.g './data-widget/data-widget.module'  
      module_.then(module_data =>{ 

      const keys = Object.getOwnPropertyNames(module_data); 
      let moduleFactories = this.compiler.compileModuleAndAllComponentsSync(module_data[keys[1]]); 
      const moduleRef = moduleFactories.ngModuleFactory.create(this.injector); 
      const componentFactory = moduleFactories.componentFactories 
      .find(e => e.selector === 'data-widget'); // find the entry component using selector  
      this.componentRef = this.container.createComponent(componentFactory, null, moduleRef.injector); 

      const newItem: WidgetComponent = this.componentRef.instance; 
     }, 
     error=>{}); 
    } 
    } 

實施例模塊和組件

數據widget.module.ts

@NgModule({ 
    imports: [ ..., 
    declarations: [DataWidget], 
    exports: [DataWidget],  
    providers: [], 
    entryComponents: [DataWidget]    
}) 
export class DataWidgetModule { 
    constructor(private widgetService: widgetService) { 
     widgetService.register('weather', DataWidget); 
    }   
} 

數據widget.component:

@Component({ 
    selector: 'data-widget', 
    templateUrl: 'data-widget.component.html' 
    }) 
    export class DataWidget{} 

所以,我怎樣才能加載外部生產模式下的模塊?

回答

0

你在說的圖書館是用於建設npm packages,Angular 2/4。

您創建一個npm package並將其發佈到npm registry。上傳後,您可以通過npm在項目中安裝該軟件包來導入它。

例子:

建立一個叫做myLib

裏面你有一個服務叫做MyService是在/exports.ts文件中導出庫

當您上傳圖書館npm registry您可以通過它導入到你的項目首先用npm install --save myLib安裝它。

那麼所需的模塊狀import { MyService } from 'myLib/exports';

+0

進口這是一個正常的過程。但是我在應用程序未知模塊的地方動態導入模塊。在我上面提到的代碼中,我們不需要通過代碼導入模塊,比如'myLib/exports'中的import {MyService};'我們只需要提供作爲'import()'方法的參數傳遞的模塊的url,並且模塊會動態地加載,並且在加載模塊後我將它編譯並獲取入口組件。所以,所有這些都在起作用。我的問題是在生產生成的腳本,我只想給模塊的URL,並自動加載,因爲它現在加載。 – Khaled

+0

你試圖實現所謂的「延遲加載」?如果是這種情況,那麼製作'npm packages'就沒有意義了,而且你應該讓常規模塊不要在你的'app.module'中註冊它們。 如何動態加載依賴關係我不知道這不應該如何完成。看看這個鏈接是否有幫助:https://angular-2-training-book.rangle.io/handout/modules/lazy-loading-module.html –

+0

是的,它的延遲加載,但動態和它的工作很好'import() 'typecript 2.4的特徵。 'import()'動態加載模塊。你只需要傳遞模塊的位置url,並且不需要提及應用中任何位置的模塊。你可以在這裏找到一個例子https://coryrylan.com/blog/angular-tips-dynamic-module-imports-with-the-angular-cli。我的代碼在開發模式下工作正常。我只需要一個生成腳本的解決方案。 – Khaled