Angular and Micro-Frontends

JavascriptHtmlAngularMicroservices

Javascript Problem Overview


I am doing some research on how to split a huge single-page-monolith into a micro-frontend architecture.

The idea:

  • the page consists of several components which would be running autonomously
  • each component is managed by one dev-team
  • each team can change, update and deploy their components without breaking components of other teams
  • each team chooses its own toolstack

The reason

To efficiently develop large applications you need to have many people working on it. However the number of developers per app/team does not scale well. Parallel development of multiple independent apps by independent teams however can be scaled arbitrarily

With this in mind it is imperative that teams can choose their own toolstack and especially perform independent version-upgrades of third party-libraries (like angular, react, jquery). If this was not the case a framework-update would need to be compatible with every single component before you could deploy it to production.

Does this work with Angular?

While independent version-upgrades are necessary, it would be reasonable to restrict the teams to a few supported frameworks (Angular, React, Vue, Polymer...) and for now I try to build a demo purely consisting of Angular-Apps.

However even though Angular 5 is supposedly a platform-framework which supports huge multi-module apps, it seems to be almost impossible to have several independent angular-apps running in the same browser window.

I managed to bootstrap several Angular-Apps (different versions, each hosted on its own server) on a single webapp by utilizing HTML-Imports. However there are several global dependencies which need to be shared between apps

  • zone.js can only be started once
  • routing requires url-changes
  • Browser-stuff like cookies, sessionstorage, etc...

There are several articles in the net on how to bootstrap multiple angular-modules but they all refer to multiple modules in the same core-app, which in turn means they all are running on the same framework-version and an update means you have to rebuild and deploy the whole monolith.

Is there any solution other than "iframes" to get multiple Angular (5) Apps running on the same Page?

Javascript Solutions


Solution 1 - Javascript

Instead of outright suggesting AGAINST this idea mainly due to separate stack requirements I will lay out the trade offs and provide some restrictions which will make this possible.

> the page consists of several components which would be running autonomously

We all know this is offered out of box in Angular components with clear demarcation of inputs and output.

Small CAVEAT: When/If you pass objects for @Input and emit event objects with @Output() interacting components must agree on a defined interface upfront.

Workaround: Create another TypeScript project which just defines these artifacts. All other "component projects" would depend on a specific version of this.

> each component is managed by one dev-team

Dev Teams can distribute the components just like other Angular projects in the opensource are doing. They can publish their artifacts to some npm repository. To develop attributable components I recommend you refer to Angular Material2 which may be overwhelming or you may use something like ngx-library-builder (based on Angular Team Member filipesilva/angular-quickstart-lib ) that each component team uses.

CAVEAT: Till this date angular team does not have a quick component library sharing project setup as evident in Angular CLI. But numerous developers have created some sort of library builders to fill the gap in Angular CLI.

> each team can change, update and deploy their components without breaking components of other teams

Have your main project pull all the components and perform a periodic/change triggered build/deploy on some CI server. This is essentially producing AOT production builds with all the latest component releases. As an added bonus you can have some abstract e2e tests built to do some automated integration testing ensuring side effects of one component does not break other components.

CAVEAT: It will be difficult to govern how each team develops the components i.e. they are doing optimal usage and disposition of memory, CPU, and other resources. e.g. what if one team starts creating subscriptions and does not remove them. Using some static code analysis can be useful but you will not have this source code available at this time - unless they also publish their source code.

> each team chooses its own toolstack

This is a complete deal breaker unless if you mean "toolstack" as in developer tools such as IDEs and some of the "devDependencies". Although certain parts of "devDependencies" of each team must have the same exact versions of angular dev kits such as compilers etc.

At the least each team must use same Angular, RxJS etc.

Most importantly care should be taken that each of the team does not bootstrap any components - only the main projects will have a bootstrap module and that will bootstrap the root component. This will help answer your zone.js issue > Does this work with Angular?

If you recognize the limitations and provide governance I suggest go for it.

Solution 2 - Javascript

We asked ourselves the same question. Unfortunately, it seems that the answer to the question

Is there any solution other than "iframes" to get multiple Angular (5) Apps running on the same Page (edit: where each Angular app can use a different Angular version)?

currently is

No, unfortunately not, as long as you want to use Angular‘s change detection (which uses zone.js).

Due to zone.js Angular pollutes the global scope. Even worse zone.js patches an awful lot of browser APIs (https://github.com/angular/zone.js/blob/master/STANDARD-APIS.md) to detect when a zone is completed.

It’s only possible to use different versions of a framework in one page without side effects if the framework does not touch global scope (this seems to be true for React und Vue). Then you can bundle different framework versions with each application via Webpack (with separated scope and the downside that the size of each application bundle increases).

So, if you want to build a web page with Angular where different applications/modules should be integrated on one page, the only feasible solution currently is to create a deployment monolith (e.g. bundle different modules from different teams in one Angular application by a CI/CD system as bhantol explained in his answer).

It seems that the Angular team is also aware of the problem and that they might tackle it with following major versions. See robwormwald’s answer on the following Github issue regarding the Angular Elements roadmap: https://github.com/angular/angular/issues/20891

Hopefully there will be more information by the Angular team on that topic when the next major version Angular 6 is release at the end of march.

Solution 3 - Javascript

It seems that there has been a solution for your needs for a while now. Take a look at Single-SPA project HERE.

It's a wrapper SPA project for your micro SPA projects.

Solution 4 - Javascript

Take a look at Angular Elements (Custom Elements). https://moduscreate.com/blog/angular-elements-ngcomponents-everywhere/

The new Ionic version (4) is totally based on it to be able to be used on every version of Angular and on every JS frameworks.

For that, they created https://stenciljs.com/ that will help you to create Custom Elements.

But if all teams are using Angular, each of them can create a library using ngm for example.

Solution 5 - Javascript

Yes you can.

However you don't really want to get stuck in a framework when you are writing web components, because the whole point of a web component is to be reused possibly anywhere.

I share your vision, it's definitely better for the quality of the software as well as the productivity of developers to work on focused features rather than large apps when it comes to implementation.

Finally, what you are looking for right now is not Angular, but StencilJS. Stencil is a compiler for web components who also generate a virtual DOM inside your component to improve it's UI performances. Check it out ;-)

Solution 6 - Javascript

Other than Iframe there is one more option is currently available is SPA framework, you can get the sample code from here

https://github.com/PlaceMe-SAS/single-spa-angular-cli-examples https://github.com/joeldenning/simple-single-spa-webpack-example

Solution 7 - Javascript

The only way to integrate different Angular Apps apart from IFrames and communication via postMessage is by "Deep-Linking" them and exchanging information using URL-Parameter. All Angular apps are then located on their own browser tab. But for common services and components you may want to implement a "Shared Kernel" used by all of your Angular apps, therefore your a stuck on a certain Angular version range. When you want this shared kernel the NGModule approach is the recommended way to go. You can mix Angular 2 and Angular 5 versions in one app because they are backward compatible. There ist no urgent need for the teams to stuck on the same version, until the Angular Team introduces breaking changes. Despite of that your technical debts grow, when you are not updating. The frequency for technical-updates is definitly higher in the Angular/Javascript area.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionH WView Question on Stackoverflow
Solution 1 - JavascriptbhantolView Answer on Stackoverflow
Solution 2 - JavascriptPhilipView Answer on Stackoverflow
Solution 3 - JavascripteddyP23View Answer on Stackoverflow
Solution 4 - JavascriptGilsdavView Answer on Stackoverflow
Solution 5 - JavascriptDevView Answer on Stackoverflow
Solution 6 - JavascriptAjiView Answer on Stackoverflow
Solution 7 - JavascriptDirk LammersView Answer on Stackoverflow