Update 5/24/2018: 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.)
Recent architectural changes in Angular 6 do bring us closer to a solution. Additionally, Angular Elements (https://angular.io/guide/elements) provides some component functionality--though not quite what I originally described in this post.
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.
I would like to implement a pluggable (plug-in) framework in an Angular 2
, Angular 4
, Angular 5
, or Angular 6
application.
(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, Angular 2/4/5/6
is a near perfect fit for most of the needs of that system.)
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 without having direct access to or knowledge of the primary application's source code or inner workings.
(That phrasing about "without having direct access to or knowledge of the application's source code or inner workings" is a core objective.)
Examples of pluggable frameworks include common content management systems like WordPress
or Drupal
.
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.
I am currently trying to determine answers (with your help) to the following five questions.
- Practicality: Is a plugin framework for an
Angular 2/4/5/6
application even practical? (Until now, I have not found any practical way to create a truly pluggable framework withAngular2/4/5/6
.) - Expected Challenges: What challenges might one encounter in implementing a plugin framework for an
Angular 2/4/5/6
application? - Implementation Strategies: What specific techniques or strategies could be employed for implementing a plugin framework for an
Angular 2/4/5/6
application? - Best Practices: What are the best practices for implementing a plugin system for an
Angular 2/4/5/6
application? - Alternative Technologies: If a plugin framework is not practical in an
Angular 2/4/5/6
application, what relatively equivalent technologies (e.g.React
) might be suitable for a modern highly reactive Web application?
In general, use of Angular 2/4/5/6
is very desirable because:
- it is naturally extremely fast--blazingly so.
- it consumes very little bandwidth (after the initial load)
- it has a relatively small footprint (after
AOT
andtree shaking
)--and that footprint continues to shrink - it is highly functional, and the Angular team and community are continuing rapid growth of its ecosystem
- it plays well with many of the best and latest Web technologies such as
TypeScript
andObservables
- Angular 5 now supports service workers (https://medium.com/@webmaxru/a-new-angular-service-worker-creating-automatic-progressive-web-apps-part-1-theory-37d7d7647cc7)
- being backed by
Google
, it is likely to be supported and enhanced well into the future
I would very much like to use Angular 2/4/5/6
for my current project. If I am able to use Angular 2/4/5/6
, I will also be using Angular-CLI
and probably Angular Universal
(for server-side rendering.)
Here are my thoughts, so far, regarding the questions above. Please review and provide your feedback and enlightenment.
Angular 2/4/5/6
apps consume packages--but this is not necessarily the same as allowing plugins within an application. A plugin in other systems (e.g.Drupal
) can be essentially added by dropping the plugin folder into a common modules directory where it is automatically "picked up" by the system. InAngular 2/4/5/6
, a package (as a plugin might be) is usually installed vianpm
, added to thepackage.json
, and then manually imported into the app--as inapp.module
. This is much more complicated than theDrupal
method of dropping a folder and having the system automatically detect the package. The more complicated it is to install a plugin, the less likely people will be to use them. It would be much better if there was a way forAngular 2/4/5/6
to automatically detect and install plugins. I am very interested to find a method which allows non-developers to install theAngular 2/4/5/6
application and install any chosen plugins without having to understand all of the application's architecture.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,
Angular 2/4/5/6
is relatively complicated and has a very lengthy learning curve. To further complicate things, most productionAngular 2/4/5/6
applications also utilizeAngular-CLI
,Angular Universal
, andWebPack
. 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 ofTypeScript
and a reasonable familiarity withNodeJS
. Are the knowledge requirements so extreme that no third party would ever want to develop a plugin?Most plugins will likely have some server side component (e.g. for storing/retrieving plugin related data) as well as some client-side output.
Angular 2/4/5
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 shreddingAngular 2/4/5/6
's security mechanisms.Most production
Angular 2/4/5/6
applications are pre-compiled usingAhead of Time
(AOT
) 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.In an
Angular 2/4/5/6
application, especially a pre-compiled one, a single piece of errant or conflicting code can break the entire application.Angular 2/4/5/6
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.
i'm currently in the same quest as you are, trying to make a Pluggable/Themable Version of Angular, and it's not a trivial problem.
I Actually Found Pretty Good Solutions, reading the book Developing with Angular by the Genius Denys Vuyika, he actually on the book explain a pretty good solution, he talks about External plugins on the page 356 of the book and Uses Rollup.js to achieve the solution, he then process to dynamically load external plugins that have been previously built outside of your application.
There is also two other libraries/projects that help you achieve this result ng-packagr and Nx extensions for Agnular (from Nrwl) we are tying to implement the latter, and i'd say it's not as smooth as we anticipated, angular was simple not built for that, so we have to work around some of the the core on how Angular, and the NX ppls are one of the best on it.
We are only at the beginning of our Open Source Project, we are using Django+Mongo+Angular, (We are calling WebDjangular and one of our possible approaches to this answer, is that Django will have to write some JSON configuration files and build the application every time a new plugin or theme is installed and activated.
What we already accomplished is, from the database we can use tags for the components like on the plugin, and the component will be printed on the screen! Again the project is in very early stages, we are basing our architecture a little bit on Wordpress, and we have a lot of more tests to do to achieve our dream :D
I Hope the Book can help you, and using Rollup.js i know you will be able to crack this non trivial problem.