Iframes, web components, packages or federation: integration techniques compared
There are four common ways to put separately owned user interfaces on one page. Each trades isolation against performance and user experience in a different way. Most real platforms use more than one.
Iframes
Each micro-frontend is a complete page shown inside an <iframe>. The browser provides the isolation: a separate document, a separate JavaScript global scope and separate CSS. The host and the frame talk through postMessage.
Strengths. Isolation is enforced by the browser, and it is the only technique here that protects against untrusted code. The sandbox attribute restricts what the frame may do.
Costs. Every frame loads its own framework and assets. Layout takes custom work: frame height, dialogs and overlays that cannot leave the frame, focus and keyboard navigation across the boundary. Deep links and the back button need a messaging protocol between host and frame.
Web components (custom elements)
Each micro-frontend exposes one or more custom elements, for example <billing-root>. The host loads a script and places the tag. The contract is framework-agnostic: attributes and properties go in, DOM events come out. In Angular, @angular/elements packages a component as a custom element.
Strengths. Any framework can host any other. The contract is a browser standard and will outlive the frameworks on both sides.
Costs. Isolation is partial. Shadow DOM scopes styles when it is used. JavaScript still shares one global scope. Each element may bring its own copy of its framework unless sharing is arranged separately. Custom element names are global and can be registered only once, which matters when two versions of the same element load on one page.
Build-time packages
Each team publishes an npm package. The host installs the packages and builds everything into one application.
Strengths. One optimized build, one framework copy, full type checking across boundaries, and tooling everyone already knows.
Costs. There is no independent deployment. Every change needs a version bump in the host, a host build and a host release. This approach is excellent for shared libraries and design systems, and weak as the main integration technique when independent releases are the goal.
Runtime federation
The host loads modules from remotes while the page is running, and shares dependencies with them. Webpack Module Federation and Native Federation both work this way.
Strengths. Independent deployment with a single framework instance. The user experience is the same as in a single application: one router, shared services, no visible seams.
Costs. Isolation is the lowest of the runtime options. Everything runs in the same JavaScript context, the same DOM and the same CSS scope, so a faulty remote can affect the page. Shared dependency versions need discipline, as explained in Shared dependencies and versions.
Comparison
| Iframes | Web components | Build-time packages | Runtime federation | |
|---|---|---|---|---|
| Isolation | Strong, enforced by the browser | Partial: styles with Shadow DOM, no JavaScript isolation | None | None beyond conventions |
| Independent deployment | Yes | Yes | No | Yes |
| Loading performance | Weakest: everything duplicated per frame | Medium: depends on whether frameworks are shared | Best | Good when sharing is configured well |
| User experience | Hardest to make seamless | Good | Seamless | Seamless |
| Mixed frameworks | Easy | Easy | Hard | Possible, with wrappers |
| Complexity | Low to start, high to polish | Medium | Low | Medium to high |
Combining them
These techniques are complementary. A typical mature platform looks like this:
- Runtime federation for the main business areas, all on the same framework.
- A custom element wrapper for the one area built in a different framework or a much older version.
- An iframe for a third-party tool, or a legacy application too fragile to load into the shared page.
- Build-time packages for the design system, the shared utilities and the typed contracts between teams.
How to choose
- Do teams need to release independently? If not, use build-time packages in a single application. It is the cheapest and fastest option.
- Do you trust all the code on the page? If any part comes from a third party or handles data that other parts must not reach, use an iframe for it. The security side is covered in Micro-frontend security.
- Is there one framework, at compatible versions? Use runtime federation.
- Are there several frameworks or incompatible versions? Use web components, or an orchestrator such as single-spa. See single-spa vs Module Federation.
Iframes are tempting as a quick start because the first demo works in a day. The cost arrives later: resizing, dialogs, shared login, navigation and accessibility across frames. Choose them when you need the isolation.
One practical rule
Pick the technique with the least isolation that still meets your trust and framework constraints. Isolation always costs performance and user experience.
More in this section
- The micro-frontend host: what it is responsible for and what it must not do
- Routing across micro-frontends: route ownership, deep links and the navigation contract
- Sharing login and session across micro-frontends
- How micro-frontends communicate, and what to avoid
Planning a migration or a micro-frontend platform?
In a 20-minute call you describe your situation and I tell you how I'd approach it. If it isn't worth doing yet, I'll say so.
Message me on LinkedIn