title: Implementing a plugin architecture / plugin system / pluggable framework in Angular 2, 4, 5, 6
body: <p><strong>Update 5/24/2018:</strong> We are now +3 versions of Angular from my original post and still don't have a final workable solution. Lars Meijdam (@LarsMeijdam) has come up with an interesting approach which is certainly worth a look-see. (Due to proprietary issues, he had to temporarily remove the GitHub repository where he had originally posted his sample. However, you may message him directly if you would like a copy. Please see the comments below for more info.) </p>
  
  <p>Recent architectural changes in Angular 6 do bring us closer to a solution. Additionally, Angular Elements (<a href="https://angular.io/guide/elements" rel="noreferrer">https://angular.io/guide/elements</a>) provides some component functionality--though not quite what I originally described in this post.</p>
  
  <p>If anyone from the amazing Angular team happens to come across this, please note that there seem to be many other people who are also very interested in this functionality. It might well be worth considering for the backlog.</p>
  
  <hr>
  
  <p>I would like to implement a pluggable (plug-in) framework in an <code>Angular 2</code>, <code>Angular 4</code>, <code>Angular 5</code>, or <code>Angular 6</code> application. </p>
  
  <p>(My specific use case for developing this pluggable framework is that I need to develop a miniature content management system. For a number of reasons not necessarily elaborated here, <code>Angular 2/4/5/6</code> is a near perfect fit for most of the needs of that system.) </p>
  
  <p>By pluggable framework (or plug-in architecture), I specifically mean a system which allows third party developers to create or extend the functionality of a  primary application through the use of pluggable components <em>without having direct access to or knowledge of the primary application's source code or inner workings</em>. </p>
  
  <p>(That phrasing about "<em>without having direct access to or knowledge of the application's source code or inner workings</em>" is a core objective.)</p>
  
  <p>Examples of pluggable frameworks include common content management systems like <code>WordPress</code> or <code>Drupal</code>. </p>
  
  <p>The ideal situation (as with Drupal) would be to simple be able to place these pluggable components (or plug-ins) into a folder, have the application auto-detect or discover them, and have them just magically "work." Having this occur in some sort of hot-pluggable manner, meaning while the app was running, would be optimum.</p>
  
  <p>I am currently trying to determine answers (<em>with your help</em>) to the following five questions. </p>
  
  <ol>
  <li><strong>Practicality:</strong> Is a plugin framework for an <code>Angular 2/4/5/6</code> application even practical? (Until now, I have not found any practical way to create a truly pluggable framework with <code>Angular2/4/5/6</code>.)</li>
  <li><strong>Expected Challenges:</strong> What challenges might one encounter in implementing a plugin framework for an <code>Angular 2/4/5/6</code> application?</li>
  <li><strong>Implementation Strategies:</strong> What specific techniques or strategies could be employed for implementing a plugin framework for an <code>Angular 2/4/5/6</code> application?</li>
  <li><strong>Best Practices:</strong> What are the best practices for implementing a plugin system for an <code>Angular 2/4/5/6</code> application?</li>
  <li><strong>Alternative Technologies:</strong> <em>If</em> a plugin framework is <em>not</em> practical in an <code>Angular 2/4/5/6</code> application, what <em>relatively equivalent</em> technologies (e.g. <code>React</code>) might be suitable for a <em>modern highly reactive Web application</em>?</li>
  </ol>
  
  <p>In general, use of <code>Angular 2/4/5/6</code> is very desirable because:</p>
  
  <ul>
  <li>it is naturally extremely fast--blazingly so.</li>
  <li>it consumes very little bandwidth (after the initial load)</li>
  <li>it has a relatively small footprint (after <code>AOT</code> and <code>tree shaking</code>)--and that footprint continues to shrink</li>
  <li>it is highly functional, and the Angular team and community are continuing rapid growth of its ecosystem</li>
  <li>it plays well with many of the best and latest Web technologies such as <code>TypeScript</code> and <code>Observables</code></li>
  <li>Angular 5 now supports service workers (<a href="https://medium.com/@webmaxru/a-new-angular-service-worker-creating-automatic-progressive-web-apps-part-1-theory-37d7d7647cc7" rel="noreferrer">https://medium.com/@webmaxru/a-new-angular-service-worker-creating-automatic-progressive-web-apps-part-1-theory-37d7d7647cc7</a>)</li>
  <li>being backed by <code>Google</code>, it is likely to be supported and enhanced well into the future</li>
  </ul>
  
  <p>I would very much like to use <code>Angular 2/4/5/6</code> for my current project. If I am able to use <code>Angular 2/4/5/6</code>, I will also be using <code>Angular-CLI</code> and probably <code>Angular Universal</code> (for server-side rendering.)</p>
  
  <p>Here are my thoughts, so far, regarding the questions above. <strong>Please review and provide your feedback and enlightenment.</strong></p>
  
  <ul>
  <li><p><code>Angular 2/4/5/6</code> apps consume packages--but this is not necessarily the same as allowing plugins within an application. A plugin in other systems (e.g. <code>Drupal</code>) can be essentially added by dropping the plugin folder into a common modules directory where it is automatically "picked up" by the system. In <code>Angular 2/4/5/6</code>, a package (as a plugin might be) is usually installed via <code>npm</code>, added to the <code>package.json</code>, and then manually imported into the app--as in <code>app.module</code>. This is much more complicated than the <code>Drupal</code> method of dropping a folder and having the system automatically detect the package. <em>The more complicated it is to install a plugin, the less likely people will be to use them.</em> It would be much better if there was a way for <code>Angular 2/4/5/6</code> to automatically detect and install plugins. I am very interested to find a method which allows non-developers to install the <code>Angular 2/4/5/6</code> application and install any chosen plugins without having to understand all of the application's architecture.</p></li>
  <li><p>Generally, one of the benefits of providing a pluggable architecture, is that it is very easy for 3rd party developers to extend the functionality of the system. Obviously, these developers will not be familiar with all of the intricacies of the code for the application they are plugging into. Once the plugins are developed, other even less technical users may simply install the application and any selected plugins. However, <code>Angular 2/4/5/6</code> is relatively complicated and has a very lengthy learning curve. To further complicate things, most production <code>Angular 2/4/5/6</code> applications also utilize <code>Angular-CLI</code>, <code>Angular Universal</code>, and <code>WebPack</code>. Someone who is implementing a plugin would probably have to have at least some basic knowledge of how all of these fit together--along with a strong working knowledge of <code>TypeScript</code> and a reasonable familiarity with <code>NodeJS</code>. Are the knowledge requirements so extreme that no third party would ever want to develop a plugin? </p></li>
  <li><p>Most plugins will likely have some server side component (e.g. for storing/retrieving plugin related data) as well as some client-side output. <code>Angular 2/4/5</code> specifically (and strongly) discourages developers from injecting their own templates at runtime--as this poses a serious security risk. In order to handle many types of output that a plugin may accommodate (e.g. display of a graph), it appears that allowing users to create content which is injected into the response stream, in one form another, is probably necessary. I wonder how it might be possible to accommodate this need without figuratively shredding <code>Angular 2/4/5/6</code>'s security mechanisms. </p></li>
  <li><p>Most production <code>Angular 2/4/5/6</code> applications are pre-compiled using <code>Ahead of Time</code> (<code>AOT</code>) compilation. (Probably all should be.) I am uncertain how plugins might be added to (or integrated with) pre-compiled applications. The best scenario would involve compiling the plugins separately from the main application. However, I am uncertain how to make this work. A fallback might be to re-compile the entire application with any included plugins but that complicates things a bit for an administrative user who simply wants to install the application (on his own server) along with any selected plugins. </p></li>
  <li><p>In an <code>Angular 2/4/5/6</code> application, especially a pre-compiled one, a single piece of errant or conflicting code can break the entire application. <code>Angular 2/4/5/6</code> applications are not always the easiest to debug. Application of ill-behaved plugins could result in very unpleasant experiences. I am currently unaware of a mechanism to gracefully handle ill-behaved plugins. </p></li>
  </ul>