Frontend Development 8 min read

Implementing Micro Frontends with Angular: A Practical Guide (Part 2)

This article explains how Outbrain built a micro‑frontend architecture using Angular lazy‑loaded modules, a custom share‑loader for cross‑app module sharing, DOM encapsulation, independent testing, and per‑app deployment via Node services, providing a concrete, framework‑agnostic solution.

Architects Research Society
Architects Research Society
Architects Research Society
Implementing Micro Frontends with Angular: A Practical Guide (Part 2)

In the previous part we discussed the motivations for moving to a micro‑frontend (MFE) solution and the criteria for selecting a suitable approach; this section describes how Outbrain implemented that solution using Angular.

Angular’s built‑in module system allows us to declare components, directives, services, and other modules in a single @NgModule({ imports: [CommonModule], declarations: [WelcomeComponent], bootstrap: [], entryComponents: [] }) export class AppB_Module {} . By specifying the module file as a Webpack entry point, the entire Angular module—including its CSS and HTML—is bundled into a single JavaScript file.

Webpack configuration adds an entry such as entry: { 'appB_module': './app/appB.prod.module.ts' } . At runtime Angular’s lazy‑loading mechanism dynamically loads this bundle via a route definition like const routes: Routes = [{ path: 'appB', loadChildren: '/appB/appB_Module#AppB_Module' }]; , moving the application toward a set of small, independently loadable mini‑apps.

To share modules between these mini‑apps without bundling everything together, a custom Webpack loader called share‑loader is introduced. In Application A the loader is configured as follows:

rules: [
  {
    test: /\.js?$/,
    use: [{
      loader: 'share-loader',
      options: {
        modules: [/@angular/, /@lodash/],
        namespace: 'container-app'
      }
    }]
  }
]

Application B’s webpack.json uses the loader’s Externals helper to expose the shared modules under the same namespace:

const { Externals } = require('share-loader');
externals: [
  Externals({
    namespace: 'container-app',
    modules: [/@angular/, /@lodash/]
  })
],
output: {
  library: 'appB',
  libraryTarget: 'umd'
}

This setup bundles Angular and Lodash into Application A while exposing them via the container-app namespace; Application B then references those modules through the same namespace, enabling selective sharing of code while keeping other modules private.

For CSS encapsulation each mini‑app is wrapped in a common Angular component that uses ViewEncapsulation.Native :

@Component({
  selector: 'ob-externals-wrapper',
  template: require('./externals-wrapper.component.pug')(),
  styleUrls: ['./externals-wrapper.component.less'],
  encapsulation: ViewEncapsulation.Native
})

This wrapper also provides an event‑bus‑based communication layer, allowing decoupled data exchange between the container and its mini‑apps and simplifying cleanup when a mini‑app is removed.

Because each mini‑app can run independently, separate test suites can be executed per app, giving teams immediate feedback on regressions in their own codebase.

Deployment is handled by giving each mini‑app its own Node service. When a new app is deployed, the service builds a JavaScript bundle and exposes an endpoint that returns the bundle’s URL. The container loads the bundle at runtime via this endpoint, enabling truly independent builds and deployments.

For a hands‑on example, readers are directed to the share‑loader repository’s README and example‑CLI sections.

The article concludes that a micro‑frontend approach, especially when implemented with Angular’s lazy‑loading and custom sharing mechanisms, improves scalability and performance, and the same principles can be applied with other front‑end frameworks.

Webpackfrontend architecturemicro frontendsAngularShare Loader
Architects Research Society
Written by

Architects Research Society

A daily treasure trove for architects, expanding your view and depth. We share enterprise, business, application, data, technology, and security architecture, discuss frameworks, planning, governance, standards, and implementation, and explore emerging styles such as microservices, event‑driven, micro‑frontend, big data, data warehousing, IoT, and AI architecture.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.