Implementierung einer Plugin-Architektur / eines Plugin-Systems / eines steckbaren Frameworks in Angular 2, 4, 5, 6

133

Update 24.05.2008: Wir sind jetzt +3 Versionen von Angular aus meinem ursprünglichen Beitrag und haben noch keine endgültige praktikable Lösung. Lars Meijdam (@LarsMeijdam) hat einen interessanten Ansatz entwickelt, der auf jeden Fall einen Blick wert ist. (Aufgrund von proprietären Problemen musste er das GitHub-Repository, in dem er sein Beispiel ursprünglich veröffentlicht hatte, vorübergehend entfernen. Sie können ihm jedoch direkt eine Nachricht senden, wenn Sie eine Kopie wünschen. Weitere Informationen finden Sie in den Kommentaren unten.)

Die jüngsten architektonischen Änderungen in Angular 6 bringen uns einer Lösung näher. Darüber hinaus bietet Angular Elements ( https://angular.io/guide/elements ) einige Komponentenfunktionen - allerdings nicht ganz das, was ich ursprünglich in diesem Beitrag beschrieben habe.

Wenn jemand aus dem erstaunlichen Angular-Team darauf stößt, beachten Sie bitte, dass es anscheinend viele andere Personen gibt, die ebenfalls sehr an dieser Funktionalität interessiert sind. Es könnte durchaus sinnvoll sein, über den Rückstand nachzudenken.


Ich möchte eine steckbare (Plug-in) Rahmen in einer implementieren Angular 2, Angular 4, Angular 5, oder Angular 6Anwendung.

(Mein spezieller Anwendungsfall für die Entwicklung dieses steckbaren Frameworks ist, dass ich ein Miniatur-Content-Management-System entwickeln muss. Aus einer Reihe von Gründen, die hier nicht unbedingt erläutert werden, Angular 2/4/5/6ist es nahezu perfekt für die meisten Anforderungen dieses Systems geeignet.)

Mit steckbarem Framework (oder Plug-in-Architektur) meine ich speziell ein System, mit dem Entwickler von Drittanbietern die Funktionalität einer primären Anwendung mithilfe steckbarer Komponenten erstellen oder erweitern können, ohne direkten Zugriff auf oder Kenntnis des Quellcodes der primären Anwendung zu haben oder Innenleben .

(Diese Formulierung über " ohne direkten Zugriff auf oder Kenntnis des Quellcodes oder des Innenlebens der Anwendung " ist ein zentrales Ziel.)

Beispiele für steckbare Frameworks sind gängige Content-Management-Systeme wie WordPressoder Drupal.

Die ideale Situation (wie bei Drupal) wäre, diese steckbaren Komponenten (oder Plug-Ins) einfach in einen Ordner zu legen, sie von der Anwendung automatisch erkennen oder erkennen zu lassen und sie einfach magisch "funktionieren" zu lassen. Dies auf eine Art Hot-Plug-fähige Weise geschehen zu lassen, dh während die App ausgeführt wurde, wäre optimal.

Ich versuche derzeit, Antworten ( mit Ihrer Hilfe ) auf die folgenden fünf Fragen zu ermitteln.

  1. Angular 2/4/5/6Praktikabilität : Ist ein Plugin-Framework für eine Anwendung überhaupt praktikabel? (Bis jetzt habe ich keinen praktischen Weg gefunden, um ein wirklich steckbares Framework mit zu erstellen Angular2/4/5/6.)
  2. Erwartete Herausforderungen: Welche Herausforderungen können bei der Implementierung eines Plugin-Frameworks für eine Angular 2/4/5/6Anwendung auftreten?
  3. Implementierungsstrategien: Welche spezifischen Techniken oder Strategien könnten zur Implementierung eines Plugin-Frameworks für eine Angular 2/4/5/6Anwendung verwendet werden?
  4. Best Practices: Was sind die Best Practices für die Implementierung eines Plugin-Systems für eine Angular 2/4/5/6Anwendung?
  5. Alternative Technologien: Wenn ein Plugin-Framework in einer Anwendung nicht praktikabel ist Angular 2/4/5/6, welche relativ äquivalenten Technologien (z. B. React) könnten für eine moderne hochreaktive Webanwendung geeignet sein ?

Im Allgemeinen ist die Verwendung von Angular 2/4/5/6sehr wünschenswert, weil:

  • es ist natürlich extrem schnell - unglaublich.
  • es verbraucht sehr wenig Bandbreite (nach dem ersten Laden)
  • es hat einen relativ kleinen Platzbedarf (nach AOTund tree shaking) - und dieser Platzbedarf schrumpft weiter
  • Es ist hochfunktional und das Angular-Team und die Community wachsen weiterhin rasant in ihrem Ökosystem
  • Es spielt sich gut mit vielen der besten und neuesten Webtechnologien wie TypeScriptundObservables
  • Angular 5 unterstützt jetzt Servicemitarbeiter ( https://medium.com/@webmaxru/a-new-angular-service-worker-creating-automatic-progressive-web-apps-part-1-theory-37d7d7647cc7 )
  • Wenn es von unterstützt wird Google, wird es wahrscheinlich auch in Zukunft unterstützt und verbessert

Ich würde es sehr gerne Angular 2/4/5/6für mein aktuelles Projekt verwenden. Wenn ich in der Lage bin zu verwenden Angular 2/4/5/6, werde ich auch verwenden Angular-CLIund wahrscheinlich Angular Universal(für serverseitiges Rendern.)

Hier sind meine bisherigen Gedanken zu den obigen Fragen. Bitte überprüfen Sie und geben Sie Ihr Feedback und Ihre Erleuchtung.

  • Angular 2/4/5/6Apps verbrauchen Pakete - dies ist jedoch nicht unbedingt dasselbe wie das Zulassen von Plugins innerhalb einer Anwendung. Ein Plugin in anderen Systemen (z. B. Drupal) kann im Wesentlichen hinzugefügt werden, indem der Plugin-Ordner in einem allgemeinen Modulverzeichnis abgelegt wird, in dem er vom System automatisch "aufgenommen" wird. In Angular 2/4/5/6wird ein Paket (wie es ein Plugin sein könnte) normalerweise über installiert npm, hinzugefügt package.jsonund dann manuell in die App importiert - wie in app.module. Dies ist viel komplizierter als das DrupalLöschen eines Ordners und das automatische Erkennen des Pakets durch das System. Je komplizierter die Installation eines Plugins ist, desto unwahrscheinlicher ist es, dass Benutzer es verwenden. Es wäre viel besser, wenn es einen Weg dafür gäbeAngular 2/4/5/6um Plugins automatisch zu erkennen und zu installieren. Ich bin sehr daran interessiert, eine Methode zu finden, mit der Nicht-Entwickler die Angular 2/4/5/6Anwendung installieren und ausgewählte Plugins installieren können, ohne die gesamte Architektur der Anwendung verstehen zu müssen.

  • Im Allgemeinen besteht einer der Vorteile der Bereitstellung einer steckbaren Architektur darin, dass es für Entwickler von Drittanbietern sehr einfach ist, die Funktionalität des Systems zu erweitern. Offensichtlich sind diese Entwickler nicht mit allen Feinheiten des Codes für die Anwendung vertraut, in die sie einstecken. Sobald die Plugins entwickelt sind, können andere, noch weniger technische Benutzer einfach die Anwendung und alle ausgewählten Plugins installieren. Ist Angular 2/4/5/6jedoch relativ kompliziert und hat eine sehr lange Lernkurve. Um weiter komplizieren Dinge, die meisten Produktion Angular 2/4/5/6nutzen Anwendungen auch Angular-CLI, Angular Universalund WebPack. Jemand, der ein Plugin implementiert, müsste wahrscheinlich zumindest einige Grundkenntnisse darüber haben, wie all diese zusammenpassen - zusammen mit einem starken Arbeitswissen überTypeScriptund eine vernünftige Vertrautheit mit NodeJS. Sind die Wissensanforderungen so extrem, dass kein Dritter jemals ein Plugin entwickeln möchte?

  • Die meisten Plugins verfügen wahrscheinlich über eine serverseitige Komponente (z. B. zum Speichern / Abrufen von Plugin-bezogenen Daten) sowie über eine clientseitige Ausgabe. Angular 2/4/5Insbesondere (und nachdrücklich) wird Entwickler davon abgehalten, zur Laufzeit eigene Vorlagen einzufügen, da dies ein ernstes Sicherheitsrisiko darstellt. Um viele Arten von Ausgaben zu verarbeiten, die ein Plugin aufnehmen kann (z. B. Anzeige eines Diagramms), scheint es wahrscheinlich erforderlich zu sein, Benutzern das Erstellen von Inhalten zu ermöglichen, die in einer anderen Form in den Antwortstrom eingefügt werden. Ich frage mich, wie es möglich sein könnte, diesem Bedarf gerecht zu werden, ohne die Angular 2/4/5/6Sicherheitsmechanismen im übertragenen Sinne zu vernichten .

  • Die meisten Produktionsanwendungen Angular 2/4/5/6werden mit Ahead of Time( AOT) compilation vorkompiliert . (Wahrscheinlich sollte alles so sein.) Ich bin mir nicht sicher, wie Plugins zu vorkompilierten Anwendungen hinzugefügt (oder in diese integriert) werden könnten. Das beste Szenario wäre das Kompilieren der Plugins getrennt von der Hauptanwendung. Ich bin mir jedoch nicht sicher, wie ich das schaffen soll. Ein Fallback könnte darin bestehen, die gesamte Anwendung mit den enthaltenen Plugins neu zu kompilieren. Dies erschwert jedoch die Verwaltung für einen Administrator, der die Anwendung einfach (auf seinem eigenen Server) zusammen mit ausgewählten Plugins installieren möchte.

  • In einer Angular 2/4/5/6Anwendung, insbesondere einer vorkompilierten, kann ein einzelner fehlerhafter oder widersprüchlicher Code die gesamte Anwendung beschädigen. Angular 2/4/5/6Anwendungen sind nicht immer am einfachsten zu debuggen. Die Anwendung von Plugins mit schlechtem Benehmen kann zu sehr unangenehmen Erfahrungen führen. Mir ist derzeit kein Mechanismus bekannt, mit dem schlecht benommene Plugins ordnungsgemäß behandelt werden können.

Anthony Gatlin
quelle
1
Meiner Meinung nach ist ein Winkel-2-Modul ein Plugin. @ Angular / Router, @ Angular / Formen, @ Angular / http, @ Angular / Material, dies sind 'Plugins' von Angular. Wir können überprüfen, wie sie 'Plugins' herstellen.
Timathon
8
@ Timathon, leider sind sie nicht gleich. Plugin-Systeme ermöglichen die Erweiterung einer Anwendung ohne Änderung des Kernanwendungscodes. Bei Verwendung von @ angle / router, @ angle / forms usw. muss der Benutzer die Anwendung ändern. Das sind wirklich Bibliotheken im Gegensatz zu Plugins. Ich bin wirklich mehr daran interessiert, Administratoren, die keine Entwickler sind, die Möglichkeit zu geben, die für sie interessantesten Plugins auszuwählen und zu verwenden, ohne die internen Details der Anwendung kennen zu müssen.
Anthony Gatlin
1
Hast du damit etwas erreicht? Ich bin daran interessiert, etwas Ähnliches auszuprobieren. Die Art und Weise, wie Angular 2 aufgebaut ist (um Module herum) Ich dachte, eine Plugin-Architektur würde wirklich gut dazu passen, aber es scheint keine Beispiele usw. zu geben
Joe
2
@ Joe, ich habe immer noch keine gute Lösung für dieses Problem. Ich dachte das gleiche wie du.
Anthony Gatlin
2
Ich habe ein Repository auf Github mit einer Lösung erstellt, die helfen könnte. Es verwendet Angular 6-Bibliotheken und 1 Basisanwendungen, die die gebündelten UMD-Bibliotheken träge laden. github.com/lmeijdam/angular-umd-dynamic-example Wenn Sie Vorschläge haben, können Sie diese gerne hinzufügen!
Lars Meijdam

Antworten:

17

Ich habe ein Repository auf Github mit einer Lösung erstellt, die helfen könnte. Es verwendet Angular 6-Bibliotheken und 1 Basisanwendungen, die die gebündelten UMD-Bibliotheken träge laden. https://github.com/lmeijdam/angular-umd-dynamic-example

Wenn Sie Vorschläge haben, können Sie diese gerne hinzufügen!

Lars Meijdam
quelle
2
Wie in einem anderen Kommentar erwähnt, musste ich das Repository aufgrund der Unternehmensrichtlinien privat machen. Ich werde es später wieder online stellen, da die Diskussionen noch andauern
Lars Meijdam,
Würde gerne Ihre Lösung sehen, bitte.
Subhan Ahmed
@Subhan, ich bin gerade damit beschäftigt, das Repository neu zu schreiben, bevor ich es wieder auf GH stelle. Gib mir ein bisschen mehr Zeit. Ansonsten können Sie mich auch direkt kontaktieren! : D
Lars Meijdam
@ lars-meijdam: wir werden noch viel warten: D ... ich auch sehr interessiert. Vielen Dank im Voraus
Uhr
17

🛠️ Github Demo Angular -Plugin-Architektur

Vielleicht kann Ivy etwas ändern, aber vorerst verwende ich die Lösung, die Angular CLI Custom Builder verwendet und die folgenden Anforderungen erfüllt:

  • AOT
  • Vermeiden Sie doppelten Code (Pakete wie @ angle / core {common, forms, router}, rxjs, tslib)
  • Verwenden Sie die gemeinsam genutzte Bibliothek in allen Plugins, VERSENDEN Sie jedoch NICHT generierte Fabriken aus dieser gemeinsam genutzten Bibliothek in jedem Plugin, sondern verwenden Sie Bibliothekscode und Fabriken erneut
  • das gleiche Maß an Optimierung, das uns Angular CLI bietet
  • Für den Import der externen Module müssen wir nur eines wissen: den Pfad der Bundle-Datei
  • Unser Code sollte das Modul erkennen und das Plugin in die Seite einfügen
  • Unterstützung des serverseitigen Renderns
  • Modul nur bei Bedarf laden

Die Verwendung ist einfach wie folgt:

ng build --project plugins --prod --modulePath=./plugin1/plugin1.module#Plugin1Module 
         --pluginName=plugin1 --sharedLibs=shared --outputPath=./src/assets/plugins

Mehr dazu in meinem Artikel:

Yurzui
quelle
Tolles Beispiel! Eine Frage. Wie kann ich OAuthTokenzur Laufzeit von unserer Haupt-App an den Bibliotheksdienst übergeben?
Yogen Darji
@yurzui können wir den gleichen Ansatz verwenden, wenn wir mehrere Winkelanwendungen haben und deren gesamte Verteilung verwenden, anstatt Module wie Plugin 1 und Plugin 2 zu erstellen?
Momin Shahzad
Könnten Sie dieses Beispiel in naher absehbarer Zeit erneut betrachten und Ivy-kompatibel machen? Wenn Sie möchten, fügen Sie bitte ein Beispiel für einen gemeinsam genutzten und gemeinsam genutzten Dienst hinzu InjectionToken, der im AppModule bereitgestellt und in andere Plugins eingefügt wird. Vielen Dank!
Jyrkka
11

Ich habe gerade ein neues Kapitel für mein Buch " Entwickeln mit Angular " veröffentlicht, das sich mit dem Thema Plugins in Angular 2+ befasst und für Leute von großem Interesse sein sollte, die versuchen, externe Plugins zu erstellen.

Wichtige Punkte:

  • Plugins
  • Erstellen von Komponenten basierend auf Zeichenfolgennamen
  • Laden der Konfiguration von externen Quellen
  • Dynamisch wechselnde Anwendungsrouten
  • Externe Plugins
  • Plugin-Bibliotheken erstellen
  • Plugins in die Anwendung laden
  • Dynamische Routen mit Plugin-Inhalten

Das Buch ist kostenlos erhältlich und hat das Modell "Bezahlen, was Sie wollen". Nehmen Sie sich eine Kopie und hoffen Sie, dass dies hilft.

Denys Vuika
quelle
Wie kann ich eine Unterkomponente durch Ihre im Buch abgebildete Plugin-Architektur ersetzen? Ich werde die Vorlage ersetzen oder vielleicht eine Eingabeeigenschaft hinzufügen ecc ... Gleichzeitig muss ich wissen, ob es eine Möglichkeit gibt, einen bereitgestellten Dienst zu überschreiben / zu erweitern.
Matteo Calò
1
@Denis Vuyka, Das Buch sieht gut aus, aber es fehlt der entscheidende Teil - die Unterstützung der AoT-Kompilierung.
Sergey Sokolov
7

Beispielanwendung mit einem funktionierenden Plugin-System (danke an Gijs für die Gründung des Github-Repos!) Https://github.com/PacktPublishing/Mastering-Angular-2-Components/tree/master/angular-2-components-chapter-10 basiert im eBook Mastering Angular 2 Components

  • Plugin-Architektur zur Erweiterung der Kernkomponenten der App
  • Datei-Plugin-System (zum einfachen Hinzufügen von Plugin-Verzeichnissen / -Dateien, ohne Kernkonfigurationsdateien zu bearbeiten oder Ihre Anwendung neu zu kompilieren!)
  • Plugins laden und dynamisch verwenden
  • Erstellen eines rudimentären Plugin-Managers zum Aktivieren / Deaktivieren von Plugins im laufenden Betrieb

Prost, Niklas

Niklas Teich
quelle
2
Sie können keinen Beispielcode von diesem Link sehen. Können Sie einen Code Pen oder JSFiddle posten?
Sean Chase
4
Ich habe das Buch gelesen, aber der Plugin-Teil ist veraltet. Es verwendet einfaches JS und SystemJS, während Angular auf Typescript und Webpack abzielt. Mit Webpack und Typescript scheint es nicht erreichbar zu sein. Ich habe eine Frage gestellt, falls Sie Lösungen gefunden haben. Hier ist der Link
Luigi Dallavalle
Dies sollte helfen: github.com/mgechev/angular-seed/issues/…
Guillaume
kann jemand bestätigen, ob oben funktioniert? Was ist, wenn wir systemjs nicht verwenden wollen
django
5

Was Sie suchen, ist das verzögerte Laden von Modulen. Hier ist ein Beispiel dafür: http://plnkr.co/edit/FDaiDvklexT68BTaNqvE?p=preview

import {Component} from '@angular/core';
import {Router} from '@angular/router';

@Component({
  selector: 'my-app',
  template: `
    <a [routerLink]="['/']">Home</a> | 
    <a [routerLink]="['/app/home']">App Home</a> |
    <a [routerLink]="['/app/lazy']">App Lazy</a>

    <hr>
    <button (click)="addRoutes()">Add Routes</button>

    <hr>
    <router-outlet></router-outlet>
  `
})
export class App {
  loaded: boolean = false;
  constructor(private router: Router) {}

  addRoutes() {
    let routerConfig = this.router.config;

    if (!this.loaded) {
      routerConfig[1].children.push({
        path: `lazy`,
        loadChildren: 'app/lazy.module#LazyModule'
      });

      this.router.resetConfig(routerConfig);
      this.loaded = true;
    }
  }
}

Am besten ... Tom

Tom ich
quelle
17
Vielen Dank, dass Sie sich die Zeit genommen haben, meine Frage zu beantworten. Ich bin mit faul geladenen Modulen vertraut, aber diese sind nicht ganz das, wonach ich suche. Faul geladene Module müssen zur Entwurfszeit noch bekannt sein. Ich möchte in der Lage sein, tatsächliche Module und Funktionen hinzuzufügen, die bei der Erstellung der ursprünglichen App nicht bekannt waren oder nicht vorgesehen waren. (Was ich suche, ist etwas Dynamischeres.) Sicherlich würden diese Komponenten (irgendeine Form von) faulem Laden verwenden, aber es ist nur ein kleines Puzzleteil. Nochmals vielen Dank für diese Antwort.
Anthony Gatlin
1
Ich bin damit einverstanden, dass dies die Frage nicht beantwortet. Das verzögerte Laden hilft bei der Plugin-Architektur nicht, da sie zur Entwurfszeit erforderlich sind. Die Daten werden einfach erst heruntergeladen / auf den Client übertragen, wenn dies erforderlich ist.
Joe
Was ist, wenn Ihre App zum Zeitpunkt der Kompilierung alle verfügbaren Plug-In-Module kennt? Wenn Sie der Plattform ein neues Modul hinzufügen, muss es mit diesem Modul neu kompiliert werden. Nur eine Idee ... Ich bin mir nicht sicher, ob dies die Größe von JS-Dateien erheblich erhöhen wird. Ich bin mir nicht sicher, ob die Funktion zum verzögerten Laden ein solches Modul in eine separate Datei einfügt und es dann verzögert lädt. Ich teile nur meine Idee ...
Vladimir Prudnikov
@VladimirPrudnikov, wenn eine Anwendung zur Kompilierungszeit alle Plugins kennen könnte, wäre das fantastisch. Die Idee ist jedoch, Plugins möglicherweise nach dem Kompilieren der Anwendung hinzufügen zu können. Dies würde ein wirklich dynamisches Einstecken von Modulen ermöglichen. Dies würde jedoch erfordern, dass die Module zum Zeitpunkt ihrer Bereitstellung ebenfalls vorkompiliert werden - und ich bin mir nicht sicher, wie dies funktionieren würde. Ich bin mir auch nicht sicher, wie ich die Version der Plugin-Module mit Angular kompatibel halten soll.
Anthony Gatlin
2

Ich habe einen Hack zum Laden und Kompilieren anderer Module in der Bootstrap-Zeit gemacht, aber ich habe das Problem der zyklischen Abhängigkeiten nicht gelöst

 const moduleFile: any = require(`./${app}/${app}.module`),
                    module = moduleFile[Object.keys(moduleFile)[0]];

 route.children.push({
     path: app,
     loadChildren: (): Promise<any> => module
 });
 promises.push(this.compiler.compileModuleAndAllComponentsAsync(module));

Fügen Sie dann in AppModule Folgendes hinzu:

{
        provide: APP_INITIALIZER,
        useFactory: AppsLoaderFactory,
        deps: [AppsLoader],
        multi: true
},
Jose Luis Berrocal
quelle
2

Ich suchte auch nach einem Plugin-System in Winkel 2/4, um eine RAD-Umgebung für eine Unternehmensanwendung bei der Arbeit zu entwickeln. Nach einigen Recherchen habe ich mich entschlossen, eine Sammlung von datenbankgespeicherten (aber möglicherweise im Dateisystem befindlichen) Pseudo-Angular-Komponenten zu implementieren.

Die in der Datenbankdatenbank gespeicherten Komponenten basieren auf ng-dynamic und die Implementierung der Hauptkomponente ähnelt der folgenden:

declare var ctx: any;

@Component({
    selector: 'my-template',
    template: `
<div>
    <div *dynamicComponent="template; context: { ctx: ctx };"></div>
</div>
  `,
    providers: [EmitterService],

})

export class MyTemplateComponent implements OnMount, AfterViewInit, OnChanges {


    // name
    private _name: string;
    get name(): string {
        return this._name;
    }
    @Input()
    set name(name: string) {
        this._name = name;        
        this.initTemplate();
    }

    template: string;
    ctx: any = null;

    private initTemplate() {

        this.templateSvc.getTemplate(this.name).subscribe(res => {
            // Load external JS with ctx implementation
            let promise1 = injectScript(res.pathJs);
            // Load external CCS
            let promise2 = injectScript(res.pathCss);

            Promise.all([promise1, promise2]).then(() => {

                // assign external component code
                this.ctx = ctx; //

                // sets the template
                this.template = res.template;

                this.injectServices();

                if (this.ctx && this.ctx.onInit) {
                    this.ctx.onInit();
                }

            });

        });

    }

Der externe Javascript-Code ähnelt Winkelkomponenten:

var ctx = {

// injected    
_httpService: {},
_emitterService: null,

// properies
model: {
    "title": "hello world!",
},


// events
onInit() {
    console.log('onInit');
},

onDestroy() {
    console.log('onDestroy');
},

onChanges(changes) {
    console.log('changes', changes);
},

customFunction1() {
    console.log('customFunction1');
},

childTemplateName: string = 'other-component'; 

};

Und die Vorlagen der Komponenten sind wie eckige Vorlagen:

<a (click)="customFunction1()">{{ ctx.model.title }}</a>
<input [(ngModel)]="ctx.model.title" type="text" />

Und könnte auch verschachtelt sein:

<a (click)="customFunction1()">{{ ctx.model.title }}</a>
<my-template [name]="childTemplateName"></my-template>

Obwohl es nicht perfekt ist, haben die Entwickler der benutzerdefinierten Komponenten ein ähnliches Framework wie in angle2 / 4.

Zarpilla
quelle
2

Dies kann "manuell" erfolgen. Da das Webpack nichts über externe (Plug-Ins) Module weiß, kann er sie nicht in Bundles aufnehmen. Also habe ich mir den Code angesehen, der von Webpack generiert wurde, und ich habe diese Codetypen in main.bundle.js gefunden:

var map = {
"./dashboard/dashboard.module": ["../../../../../src/app/dashboard/dashboard.module.ts","dashboard.module"]}; 

Untersuchen wir, was dieses Array enthält:

  1. "./dashboard/dashboard.module" - Dies ist die Routing-URL des Moduls, das wir verzögert laden möchten, zum Beispiel: {Pfad: 'Dashboard', loadChildren: './dashboard/dashboard.module#DashboardModule'}
  2. "../../../../../src/app/dashboard/dashboard.module.ts" - Dies ist der Einstiegspunkt (Konstruktor) von
  3. "dashboard.module" - tatsächlicher Dateiname ohne chunk.js (zum Beispiel: dashboard.module.chunk.js )

Wenn Sie also theoretisch einen Eintrag zur Map-Eigenschaft hinzufügen, Ihr Routing konfigurieren und dem Muster folgen, können Sie ein Plug-In-System verwenden. Die Herausforderung besteht nun darin, Einträge zu dieser Karteneigenschaft hinzuzufügen oder daraus zu entfernen. Offensichtlich kann es nicht aus Winkelcode gemacht werden, es sollte für ein externes Werkzeug gemacht werden.

Niki Uzun
quelle
2

Ich habe versucht, eine Plugin-Architektur unter Verwendung von ABP, Angular und ASP.NET Core zu implementieren: https://github.com/chanjunweimy/abp_plugin_with_ui

Grundsätzlich habe ich Winkel-Plugins mit verschiedenen Winkelanwendungen entwickelt und diese dann dynamisch addiert.

Weitere Informationen darüber, wie ich es erreiche:

Ich habe 2 Angular-Cli-Anwendungen, 1 ist die Haupt-Angular-Cli-Anwendung und eine andere ist die Plugin-Angular-Cli-Anwendung. Das Problem, mit dem wir beim Ansatz der Angular-Cli-Plugin-Architektur konfrontiert sind, besteht darin, wie wir sie integrieren.

Im Moment habe ich ng-build für beide Anwendungen ausgeführt und sie in einem "wwwroot" -Ordner abgelegt, der dann auf einem ASP.NET Core 2.0-Server gehostet wurde. Ein einfacheres Repository, das diese Idee zeigt, ist Angular Multiple App: https://github.com/chanjunweimy/angular-multiple-app

abp_plugin_with_ui ist ein Repository, das an der Entwicklung eines Plugins arbeitet, das sowohl das Backend als auch Angular cli enthält. Für das Backend habe ich das Aspnetboilerplate-Framework verwendet, das das Frontend mit mehreren Angular-Cli-Anwendungen entwickelt.

Um die Hauptanwendung in die Plugin-Anwendung zu integrieren, müssen wir "ng-build" für beide Anwendungen ausführen (beachten Sie, dass wir auch in href der Plugin-Anwendung wechseln müssen), und dann den erstellten Inhalt des Plugins verschieben Angular Cli-Anwendung, zum Hauptanwendungsordner "wwwroot". Nachdem dies alles erreicht ist, können wir "dotnet run" ausführen, um die ASP.NET Core 2.0-Webanwendung zum Hosten der durch "ng build" generierten statischen Dateien bereitzustellen.

Hoffentlich hilft es. Kommentare sind willkommen! ^^

Junwei Chan
quelle
Ich versuche, Ihren Plugin-Dokumenten zu folgen, aber ich denke, die Dokumentation überspringt ein paar Schritte. Ich entschuldige mich, wenn ich es falsch verstehe. Das ganze "Hinzufügen eines Plugins" ist mir nicht klar. Ich bin diesem Schritt für Schritt gefolgt, aber ich sehe nicht wirklich Ergebnisse. Was muss ich an Port 4200 sehen, nachdem ich die Power Shell ausgeführt habe? Ich sehe keinen Plugins-Ordner in /aspnet-core/src/Todo.MainProject.Web.Host/. Ich habe die Powershell ausgeführt und dieser Ordner wurde nicht erstellt. Jede Hilfe geschätzt. Ich denke, Ihr Ansatz ist das, was ich brauche, aber ich bin ein bisschen unklar, wie es noch funktioniert.
Brian Kitt
OK. Ich hätte das tun sollen, bevor ich die Frage gestellt habe. Ich verbrachte Zeit mit dem Debuggen und fand meine Antworten heraus. # 1) Die Powershell platziert die ZIP-Datei nicht dort, wo sie benötigt wird. Ich muss den Plugin-Ordner erstellen und die Zip-Datei verschieben. # 2) Wenn die eckige App gestartet wird, ruft sie den Loader dynamisch auf und kopiert Plugins in die Webroot. Das war irgendwie formuliert, aber ich verstehe es jetzt. # 3) Ich muss die URL verwenden, um das Plugin aufzurufen, es wird nirgendwo angezeigt. Ich hatte erwartet, dass es auf dem Armaturenbrett sein würde. Vielen Dank für Ihre Arbeit, dies ist ein bedeutender Teil des Codes.
Brian Kitt
2

Ein wenig abseits des Themas, aber UI-Komponentenbibliotheken könnten für einige der Leser von Interesse sein, die nach Plugins suchen:
https://medium.com/@nikolasleblanc/building-an-angular-4-component-library-with-the -angular-cli-and-ng-packagr-53b2ade0701e

NativeScript verfügt über integrierte UI-Plugins:
https://docs.nativescript.org/plugins/building-plugins
Diese Plugins benötigen einen Angular Wrapper:
https://docs.nativescript.org/plugins/angular-plugin

RaSor
quelle
2

Ich bin derzeit auf der gleichen Suche wie Sie und versuche, eine steckbare / themenfähige Version von Angular zu erstellen. Dies ist kein triviales Problem.

Ich fand tatsächlich ziemlich gute Lösungen, las das Buch Entwickeln mit Angular von dem Genie Denys Vuyika , er erklärte tatsächlich auf dem Buch eine ziemlich gute Lösung, er spricht über externe Plugins auf Seite 356 des Buches und verwendet Rollup.js , um das zu erreichen Anschließend verarbeitet er das dynamische Laden externer Plugins, die zuvor außerhalb Ihrer Anwendung erstellt wurden.

Es gibt auch zwei andere Bibliotheken / Projekte, die Ihnen dabei helfen, dieses Ergebnis zu erzielen. Ng-packagr und Nx-Erweiterungen für Agnular (von Nrwl), die wir für die Implementierung des letzteren verwenden, und ich würde sagen, es ist nicht so reibungslos wie erwartet, Angular war einfach nicht dafür gebaut, also müssen wir einen Teil des Kerns daran herumarbeiten, wie Angular und die NX-Leute eines der besten sind.

Wir stehen erst am Anfang unseres Open Source-Projekts und verwenden Django + Mongo + Angular. (Wir rufen WebDjangular auf und einer unserer möglichen Ansätze für diese Antwort ist, dass Django einige JSON-Konfigurationsdateien schreiben und die erstellen muss Anwendung jedes Mal, wenn ein neues Plugin oder Theme installiert und aktiviert wird.

Was wir bereits erreicht haben, ist, dass wir aus der Datenbank Tags für die Komponenten wie im Plugin verwenden können und die Komponente auf dem Bildschirm gedruckt wird! Das Projekt befindet sich wieder in einem sehr frühen Stadium. Wir stützen unsere Architektur ein wenig auf Wordpress und müssen noch viele weitere Tests durchführen, um unseren Traum zu verwirklichen: D.

Ich hoffe, das Buch kann Ihnen helfen, und mit Rollup.js weiß ich, dass Sie dieses nicht triviale Problem lösen können.

Paulo Peres Junior
quelle