Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing a plugin architecture / plugin system / pluggable framework in Angular 2, 4, 5, 6

Update

For Angular 11 I strongly recommend you to take a look at implementation with Webpack 5 Module Federation

🎉 https://github.com/alexzuza/angular-plugin-architecture-with-module-federation

Previos version

🛠️ Github demo angular-plugin-architecture

Maybe Ivy can change something but for the time being I use the solution that uses Angular CLI Custom Builder and meets the following requirements:

  • AOT
  • avoid duplicate code(packages like @angular/core{common,forms,router},rxjs,tslib)
  • use shared library in all plugins but DO NOT SHIP generated factories from that shared library in each plugin but rather reuse library code and factories
  • the same level of optimization that Angular CLI gives us
  • for importing the external modules we just need to know only one thing: their bundle file path
  • our code should recognize module and place plugin into the page
  • support server-side rendering
  • load module only when needed

The usage is simple as:

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

More on this in my article:

  • Building extensible Dynamic Pluggable Enterprise Application with Angular

I created a repository on github with a solution which might help. It uses Angular 6 libraries and 1 base applications which load up the UMD bundled libraries lazily; https://github.com/lmeijdam/angular-umd-dynamic-example

If you have any suggestions, please feel free to add!


I have just published a new chapter for my book "Developing with Angular" that addresses the topic of plugins in Angular 2+ and should be of a great interest to people that are trying to build external plugins.

Key points:

  • Plugins
  • Building components based on string names
  • Loading configuration from external sources
  • Dynamically changing application routes
  • External plugins
  • Creating plugin libraries
  • Loading plugins into the application
  • Dynamic routes with plugin content

The book is free to get, and has "pay what you want" model. Feel free to grab a copy and hope that helps.


Example application with a working plugin system (thanks to Gijs for founding the github repo!) https://github.com/PacktPublishing/Mastering-Angular-2-Components/tree/master/angular-2-components-chapter-10 based on the eBook Mastering Angular 2 Components

  • plugin architecture to extend core app components
  • file plugin system (for simply adding plugin directories/files without editing any core config files or the need to recompile your application!)
  • load and dynamically use plugins
  • building a rudimentary plugin manager to activate/deactive plugins on-the-fly

Cheers, Niklas


What you're looking for is lazy module loading. Here is an example of it: 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;
    }
  }
}

Best...Tom