Laden Sie neue Module, die dynamisch während der Laufzeit mit Winkel-CLI & Winkel 5
Derzeit arbeite ich an einem Projekt, die gehostet wird auf einem Kunden server. Für die neuen "Module" gibt es nicht die Absicht, neu zu kompilieren die gesamte Anwendung. Das heißt, der client will update der router/lazy geladene Module in der runtime. Ich habe versucht, verschiedene Dinge aus, aber ich kann nicht ankommen es zu wirken. Ich Frage mich, ob einer von Euch weiß, was könnte ich noch versuchen oder was habe ich verpasst.
Eine Sache, die ich bemerkt, die meisten Ressourcen, die ich habe versucht, mit Winkel-cli, sind gebündelt in einzelne Brocken, die von webpack standardmäßig beim erstellen der Anwendung. Das scheint logisch, denn es macht Gebrauch von der webpack-code aufteilen. aber was ist, wenn das Modul noch nicht bekannt ist zur compile-Zeit (aber ein kompiliertes Modul ist irgendwo gespeichert auf einem server)? Die Bündelung funktioniert nicht, weil es nicht finden können, das Modul zu importieren. Und Mit SystemJS lädt UMD-Module, wenn auf dem system gefunden, aber auch gebündelt in einem separaten chunk webpack.
Einige Ressourcen, die ich schon ausprobiert;
- dynamic-remote-Komponente-loader
- Modul-laden
- Laden von Modulen, die aus verschiedenen server zur Laufzeit
- Gewusst wie: laden von dynamischen externen Komponenten in Eckigen Anwendung
- Die Implementierung einer plugin-Architektur /plugins /pluggable framework in den Winkel-2, 4, 5, 6
- Winkel-5 - load-Module (das sind nicht bekannt, zur compile-Zeit) dynamisch zur Laufzeit
- https://medium.com/@nikolasleblanc/building-an-angular-4-component-library-with-the-angular-cli-and-ng-packagr-53b2ade0701e
- Einige andere über dieses Thema.
Einigen code habe ich schon versucht und implementieren, aber nicht arbeiten in dieser Zeit;
Ausweitung der router mit dem normalen Modul.ts-Datei
this.router.config.push({
path: "external",
loadChildren: () =>
System.import("./module/external.module").then(
module => module["ExternalModule"],
() => {
throw { loadChunkError: true };
}
)
});
Normalen SystemJS Import von UMD-bundle
System.import("./external/bundles/external.umd.js").then(modules => {
console.log(modules);
this.compiler.compileModuleAndAllComponentsAsync(modules['External']).then(compiled => {
const m = compiled.ngModuleFactory.create(this.injector);
const factory = compiled.componentFactories[0];
const cmp = factory.create(this.injector, [], null, m);
});
});
Importieren von externen Modul funktioniert nicht mit webpack (afaik)
const url = 'https://gist.githubusercontent.com/dianadujing/a7bbbf191349182e1d459286dba0282f/raw/c23281f8c5fabb10ab9d144489316919e4233d11/app.module.ts';
const importer = (url:any) => Observable.fromPromise(System.import(url));
console.log('importer:', importer);
importer(url)
.subscribe((modules) => {
console.log('modules:', modules, modules['AppModule']);
this.cfr = this.compiler.compileModuleAndAllComponentsSync(modules['AppModule']);
console.log(this.cfr,',', this.cfr.componentFactories[0]);
this.external.createComponent(this.cfr.componentFactories[0], 0);
});
Verwenden SystemJsNgModuleLoader
this.loader.load('app/lazy/lazy.module#LazyModule').then((moduleFactory: NgModuleFactory<any>) => {
console.log(moduleFactory);
const entryComponent = (<any>moduleFactory.moduleType).entry;
const moduleRef = moduleFactory.create(this.injector);
const compFactory = moduleRef.componentFactoryResolver.resolveComponentFactory(entryComponent);
});
Habe versucht, laden Sie ein Modul gemacht, mit rollup
this.http.get(`./myplugin/${metadataFileName}`)
.map(res => res.json())
.map((metadata: PluginMetadata) => {
//create the element to load in the module and factories
const script = document.createElement('script');
script.src = `./myplugin/${factoryFileName}`;
script.onload = () => {
//rollup builds the bundle so it's attached to the window object when loaded in
const moduleFactory: NgModuleFactory<any> = window[metadata.name][metadata.moduleName + factorySuffix];
const moduleRef = moduleFactory.create(this.injector);
//use the entry point token to grab the component type that we should be rendering
const compType = moduleRef.injector.get(pluginEntryPointToken);
const compFactory = moduleRef.componentFactoryResolver.resolveComponentFactory(compType);
//Works perfectly in debug, but when building for production it returns an error 'cannot find name Component of undefined'
//Not getting it to work with the router module.
}
document.head.appendChild(script);
}).subscribe();
Beispiel mit SystemJsNgModuleLoader funktioniert nur, wenn das Modul bereits zur Verfügung gestellt, die als 'faul' route in der RouterModule der app (die verwandelt es in ein Stück, wenn gebaut mit webpack)
Fand ich eine viel Diskussion über dieses Thema auf StackOverflow hier und da, und Lösungen scheinen wirklich gut der laden von Modulen/Komponenten dynamisch, wenn bekannt vor. aber keiner ist passend für unseren use-case des Projekts. Bitte lassen Sie mich wissen, was ich noch versuchen kann, oder Tauchen Sie ein in.
Dank!
EDIT: ich habe gefunden; https://github.com/kirjs/angular-dynamic-module-loading und geben dieses ein versuchen.
UPDATE: ich;ve erstellt ein repository mit einem Beispiel für das laden von Modulen, die dynamisch mit SystemJS (und mit Winkel-6); https://github.com/lmeijdam/angular-umd-dynamic-example
InformationsquelleAutor Lars Meijdam | 2018-05-03
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich Stand vor dem gleichen problem. Soweit ich es verstehe, bis jetzt:
Webpack stellt alle Ressourcen bündeln und ersetzt alle
System.import
mit__webpack_require__
. Deshalb, wenn Sie wollen, zu laden, ein Modul dynamisch zur Laufzeit mithilfe von SystemJsNgModuleLoader, der Lader suchen, werden für das Modul im bundle an. Wenn das Modul nicht vorhanden ist in dem bundle, erhalten Sie eine Fehlermeldung. Webpack ist nicht Fragen Sie den server für das Modul. Dies ist ein problem für uns, da wollen wir ein Modul geladen, dass wir nicht wissen, zu bauen/kompilieren.Was wir brauchen, ist der loader, der lädt das Modul für uns (Laufzeit faul und dynamisch). In meinem Beispiel, ich bin mit SystemJS und Winkel-6 /CLI.
app.Komponente.ts
meine-dynamisch.Komponente.ts
anderen.Komponente.ts
Wie Sie sehen können, können wir sagen, SystemJS welche Module sind bereits in unsere bundle. So brauchen wir nicht wieder geladen werden (
SystemJS.set
). Alle anderen Module, die wir importieren in unseremy-dynamic-component
(in diesem Beispielother
) werden vom server angefordert zur Laufzeit.Die dynamische Komponente in deinem Beispiel, wo ist diese angesiedelt? Hast du eine Bibliothek (ng g lib <name>) ersten und nutzen das UMC-Modul erhalten Sie aus dem Bau der Bibliothek ? Oder tun Sie transpile es sich vor dem servieren/Aufbau der gesamten Anwendung? Ansonsten hat man ein plunkr oder?
Mein setup ist ein wenig komplexer. Daher bin ich nicht sicher. So bald, wie Sie ausführen
SystemJS.import('my-dynamic.component.js').then()
Sie werden sehen, wo dein browser ist nicht auf der Suche für Sie. Sollte es in den root-Ordner Ihrer app oder nebenAppComponent
. Ich benutze Visual Studio ein Visual Studio ist transpiling meinemy-dynamic.component.ts
. Sie können tsc-mein-dynamisch.Komponente.ts, Wenn ich einige Zeit erstelle ich eine plunkr. Aber bis dann werde ich meine Antwort hier.Ich erstellt einfach ein github: github.com/mrmscmike/ngx-dynamic-module-loader Es ist nur ein Entwurf und wir sicher brauchen, um es zu verbessern. Vielleicht können wir sammeln unsere Erfahrungen. Jede Hilfe ist willkommen.
Ich glaube, ich weiß, was das problem mit "Keine NgModule Metadaten gefunden für 'nicht definiert'". Wenn Sie sich Ihre
*.umd.js
und vergleichen Sie es mit dem Beispielmy.module.js
können Sie sehen, dass meine.Modul hat die folgendenexports["default"] = MyModule;
. Der Winkel 6 lib hatexports.MyModule = MyModule;
. Wenn SiecompileModuleAndAllComponentsAsync(module['PluginModule'])
es funktioniert. Keine Ahnung, wie man.default
arbeitenInformationsquelleAutor Michael
Habe ich die https://github.com/kirjs/angular-dynamic-module-loading Lösung mit eckiger 6-Bibliothek-Unterstützung so erstellen Sie eine Anwendung, die ich gemeinsam auf Github. Wegen Gesellschaft, die Politik, die es brauchte, offline geschaltet werden. Sobald die Diskussionen über über die Beispiel-source-Projekt Teile ich es auf Github!
UPDATE: repo gefunden werden können ; https://github.com/lmeijdam/angular-umd-dynamic-example
assets
. Wie über die Verknüpfung zu einer typescript-Modul? muss zuerst umgewandelt js manuell kopiert.die Lösung, die wir in unser Projekt gesucht wurde, mehr auf die kompilierte Module (JS), laden Sie Sie dynamisch von einem server (die ist noch fraglich). so würde es nur laden "fertig" - Module, die platziert wurden, in einem bestimmten Ordner, Typoskript nicht, obwohl
InformationsquelleAutor Lars Meijdam
Ich glaube, dass dies möglich ist, mit SystemJS laden einer UMD-bundle wenn Sie erstellen und führen Sie Ihre wichtigsten Anwendung mit webpack. Ich benutzte eine Lösung mit ng-packagr zu bauen UMD-bundle der dynamischen plugin - /addon-Modul. Dies github veranschaulicht das Verfahren beschrieben:
https://github.com/nmarra/dynamic-module-loading
InformationsquelleAutor N.M.
Tun es mit eckiger 6-Bibliothek und rollup den trick tun. Ich habe einfach ein wenig Experimentieren mit ihm, und ich kann teilen standalone-Winkel-AOT-Modul mit der Haupt app ohne rebuild letzten.
In eckigen library set angularCompilerOptions.skipTemplateCodegen auf false und nach dem build-Bibliothek erhalten Sie Modul-factory.
Danach bauen Sie eine umd-Modul mit rollup wie diese: rollup
dist/plugin/esm2015/lib/plugin.module.ngfactory.js --Datei src/assets/plugin.module.umd.js --format umd --name-plugin
Hier https://github.com/iwnow/angular-plugin-example finden Sie, wie entwickeln plugin mit eigenständigen Gebäude und AOT
Ein Problem mit diesem setup ist, dass, wenn das plugin-Projekt importiert ein Angular Modul die Eingabe-Komponenten aufgeführt, generiert plugin UMD wird am Ende mit Fabriken aller aufgeführten Komponenten in Eingabe-Komponenten.
InformationsquelleAutor Vitaliy Vostroknutov
Ja, Sie können den lazy load-Module unter Verwendung von verweisen als Module in den router. Hier ist ein Beispiel https://github.com/start-angular/SB-Admin-BS4-Angular-6
InformationsquelleAutor Jaya Krishna
Ich getestet habe, im Winkel 6, unten-Lösung für das dynamische laden eines Moduls aus einer externen Paket oder einem internen Modul.
1. Wenn Sie möchten, um dynamisch geladen, ein Modul aus einer Bibliothek-Projekt oder ein Paket:
Habe ich ein Bibliothek-Projekt "admin" aus (oder verwenden Sie ein Paket) und eine Anwendung-Projekt "app".
In meinem "admin" - Bibliothek-Projekt, ich habe AdminModule und AdminRoutingModule.
In meiner "app" - Projekt:
ein. Veränderung im tsconfig.app.json:
b. In-app-routing.- Modul.ts:
2. wenn Sie möchten laden Sie ein Modul aus dem gleichen Projekt.
Gibt es 4 verschiedene Optionen:
ein. In-app-routing.- Modul.ts:
Das ist toll. Ich habe auf der Suche für eine Lösung ähnlich wie mit Ihrem Fall. Aber der Unterschied ist, dass, würde ich mag, um eine Konfigurationsdatei, um eine Liste aller Module, dann laden Sie dann in der Anwendung dynamisch ist. Leider, ist mein Ansatz (Fall 1), oben noch einige Probleme hat. d.h. um
await import(...)
ich nicht verwenden können, eine variable, was bedeutet, ich kann immer noch nicht das Ziel erreicht werden dynamisch geladen, alle Pakete. Aber Fall 2 funktioniert einwandfrei. Ich bin noch auf der Arbeit mit webpack, um zu sehen, wenn es irgendeinen anderen Anhaltspunkt.Haben Sie überprüft, mein github-Projekt, das bereits zum Ende der Frage ?:) Dies könnte eine Hilfe!;) github.com/lmeijdam/angular-umd-dynamic-example
Ich danke Ihnen sehr. Es funktioniert gut. Das laden von einer URL ist eine wirklich gute Lösung. 🙂
InformationsquelleAutor Robin Ding