2017-09-15 2 views
0

La fonction de type dactylographique 2.4 [import()][1] aide à charger dynamiquement le module. J'ai essayé cette fonctionnalité et cela fonctionne bien. Je suis capable de charger le module et les composants ensemble dynamiquement chaque fois qu'il écrit en tapuscrit et les modules importés sont dans le même dossier.Comment importer des modules externes ou des plugins de manière dynamique en utilisant la fonction import() de typecript 2.4 dans le script généré par la production CLI Angular

Le problème commence quand j'ai essayé de le construire en mode production. J'utilise Angular-CLI et construire mon projet en mode production et il a généré javascript paquets. Maintenant, je suis confus pour charger les modules.

Je suis en train de développer une fonction basée sur un plugin où l'on peut ajouter différents plugins dynamiquement. Ainsi, ces plugins sont séparés de l'application principale et peuvent être ajoutés dynamiquement en utilisant la méthode import(). Au début, j'ai développé les plugins en tapuscrit et ces plugins sont chargés en utilisant la méthode import() parfaitement. Mais en mode production, les plugins doivent être une bibliothèque javascript pouvant être importée en utilisant la méthode import(). J'ai donc converti les plugins dans une bibliothèque en utilisant https://github.com/jvandemo/generator-angular2-library. et essayé d'importer le fichier index.js. Mais il donne un message d'erreur "ERROR Error: Uncaught (in promise): Error: No NgModule metadata found for 'undefined'."

Le code suivant que j'ai utilisé pour importer des modules et des composants dynamiquement.

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=>{}); 
    } 
    } 

module exemple et les composants sont

données-widget.module.ts

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

données widget.component:

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

Alors, comment puis-je charger externe modules en mode production?

Répondre

0

La bibliothèque dont vous parlez est destinée à la construction npm packages, avec Angular 2/4.

Vous créez un npm package et le publiez sur npm registry. Une fois téléchargé, vous pouvez l'importer en installant le package dans votre projet via npm.

Exemple:

Faire une bibliothèque appelée myLib

A l'intérieur vous avez un service appelé MyService qui est exporté dans /exports.ts fichier

Lorsque vous téléchargez la bibliothèque npm registry vous pouvez importer dans votre projet d'abord l'installer avec npm install --save myLib.

importer ensuite dans votre module comme import { MyService } from 'myLib/exports';

+0

Ceci est un processus normal. Mais j'importe les modules dynamiquement là où les modules sont inconnus par l'application. Dans mon code mentionné ci-dessus, nous n'avons pas besoin d'importer des modules par le code 'comme import {MyService} de' myLib/exports ';' Nous devons fournir seulement l'url du module qui passe en paramètre de la méthode 'import()' et du chargement dynamique du module et après le chargement du module je le compile et récupère les composants d'entrée.Donc, tout cela fonctionne. Mon problème est dans le script de production généré où je voudrais seulement donner l'URL du module et charger automatiquement comme il charge maintenant. – Khaled

+0

Vous essayez d'implémenter ce qu'on appelle un «chargement paresseux»? Si tel est le cas, il ne sert à rien de faire des paquets npm et vous devriez plutôt faire en sorte que les modules réguliers ne les inscrivent pas dans votre app.module. Comment charger dynamiquement les dépendances Je ne sais pas car ce n'est pas comme cela que ça doit être fait. Voir si ce lien aide: https://angular-2-training-book.rangle.io/handout/modules/lazy-loading-module.html –

+0

oui, son chargement paresseux mais dynamiquement et son fonctionnement bien avec 'import() 'Caractéristique du typecript 2.4. 'import()' charge dynamiquement le module. vous avez juste besoin de passer une URL de localisation du module et n'avez pas besoin de mentionner le module n'importe où dans l'application. Vous pouvez trouver un exemple ici https://coryrylan.com/blog/angular-tips-dynamic-module-imports-with-the-angular-cli. Mon code fonctionne bien en mode de développement. J'ai juste besoin d'une solution pour le script généré en production. – Khaled