I would like to present a multi-framework, multi-bundle orchestration layer, supporting the oldest to the newest technologies of micro frontends. Framework leverages the power of Webpack to work hand in hand to coordinate and route multi-bundle applications without the overhead.
This approach becomes crucial when an application outgrows all reasonable limits — the build process is slow, every minor change results in minutes of compilation in watch mode, and the codebase contains thousands of modules and NPM dependencies. At this point, the support of this monster becomes too expensive.
The problem becomes even worse if the team decides to try a new, improved technology stack. You can attempt to gradually replace the old system with the new one. At we’ve been through that: we attempted to refactor one monolith and replace it with another monolith. Both were rapidly growing and receiving addition of new features, so when we finished, the final monolith was enormous. At some point it became obvious that it’s time to divide it before it’s too late, so we introduced embeddable sub-apps, but each was developed by a different team and had its own interface to connect to the host, its own bus, and some of them were IFrames. This approach helped in the short term, but was suboptimal in terms of further scaling.
Before we start, let’s first figure out the basic terms:
Apps can’t talk directly to each other, but host wire them together
The Web Apps Framework
The Web Apps framework provides exactly this:
A framework agnostic way to inject any app into any app, with a unified communication interface along with other perks.
Of course, there are other frameworks that do similar things, but Web Apps is using a very elegant and minimalistic approach to loading and wrapping different kinds of apps, which provides a unified interface no matter which underlying technologies are being used: Angular, Vue, React, jQuery, no JS at all, you name it.
The concept of this framework is to:
Load an App with certain type & URL (one or many)
Render the App on the page in any place
Wire events between Host and the App, including navigation events
Communication can be event-based or through props (or HTML attributes). Events with will be transmitted to any type of app, including IFrame, through the same interface, so the Host can swap them at any time and should not care what type of app it’s showing. The Host can even swap URL and type of an App dynamically, let’s say, based on location, and show different apps in the main content area (just like in the ).
How to define an app?
There are no special techniques to prepare apps for embedding; just a tiny wrapper, depending on the type of app:
With a bit of additional code using, all attributes can be synchronized from host to app.
If Module Federation is not available on the host inject your app into a given DOM Node, with a JSONP-style callback, as follows:
Another way is to wrap the app in a Web Component for better isolation of CSS styles using Shadow DOM and Shadow CSS, as follows:
With observable attributes you can sync them to React app as props.
Using IFrames does not require any code at all, but if you want to communicate just add this:
What about sharing?
Obviously, if each app begins to have its own build, it also carries all the common dependencies, likeor . This, at times, can be quite heavy. Luckily, there’s a fancy new technology that aims to solve this problem:
The big win is that the Web Apps framework has out of the box support for which allows sharing of modules between host and apps, and apps between other apps. This especially plays well with small footprint of the framework. Module Federation has many features including automatic healing, redundancy and proper versioning. You can just follow the example and :
And this is it! Now your host and app can share dependencies in a clean and transparent way.
More about IFrames
Of course, one can just display an IFrame with a legacy app, no big deal. But big problems may occur when sub-apps are contained within IFrames and wish to send and receive messages from the host and show popups.
Messaging can be solved via PostMessage, but Web Apps simplifies and standardizes the interface, making sure there’s no flood of broadcast post messages and that only proper targets will receive them.
Dealing with the popups problem is a bit trickier:
Note the visual separation of app and host
… the gray backdrop behind the popup is contained within the IFrame, while the rest of the website has a white background, meh, ugly!
Can we tell the host that the IFrame’d app is showing a popup? What if the host wants the IFrame’d app to hide it?
This is exactly what the Web Apps Framework is doing: it makes sure the Host is aware when to show the backdrop and what color it should be. It can send an event to the IFrame’d App when it’s time to close the popup, so it looks seamless:
Backgrounds inside and outside of IFrame are the same
Framework also supports synchronization of IFrame height and it’s contents, so that long texts in frames aren’t cut.
Let me summarize the key features of the Web Apps Framework:
Module Federation support
Location synchronization between app and host
Ability to deep-link “app to app” or “app to host” or “host to app”
Consistent event-based interaction between apps and host
IFrame resizing based on the content of an IFrame
IFrame popup support
Maximum adherence to Web Standards
Written in TypeScript
React and Web Component host helpers
Unlimited nesting of apps within other apps, e.g. each app can become a host for more apps
Seamless navigation support