New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@angular-architects/module-federation-tools

Package Overview
Dependencies
Maintainers
1
Versions
77
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@angular-architects/module-federation-tools

Add-on for ``@angular-architects/module-federation`` helping to reduce boiler plate code.

  • 14.0.0
  • npm
  • Socket score

Version published
Maintainers
1
Created
Source

@angular-architects/module-federation-tools

Add-on for @angular-architects/module-federation helping to reduce boiler plate code.

The current release is focusing on combining web components with module federation for multi framework and multi version micro frontends:

Example

By compiling and loading these web components via module federation, we can share libraries like Angular if they use the same version. Otherwise, module federation would decide at runtime to load a dedicated version of the lib for the micro frontend in question:

Venn

This can help to balance the trade-off between bundle size and isolation of micro frontends.

Disclaimer: Multi-Framework and -Version Micro increase the overall complexity and call for some workarounds. This library tries to hide some of them.

Examples

Tutorial

Please find our tutorial here.

Providing a Web Component with Module Federation

Expose your Angular components via Angular Elements:

import { createCustomElement } from '@angular/elements';
[...]

@NgModule({
  [...]
  declarations: [
    AppComponent
  ],
  bootstrap: [] // No bootstrap components!
})
export class AppModule {
  constructor(private injector: Injector) {
  }

  ngDoBootstrap() {
    const ce = createCustomElement(AppComponent, {injector: this.injector});
    customElements.define('angular1-element', ce);
  }

}

Add @angular-architects/module-federation to your micro frontend:

ng add @angular-architects/module-federation

Make your webpack.config.js expose the whole bootstrap.ts that bootstraps your AppModule.

// webpack.config.js
name: "angular3",
library: { type: "var", name: "angular3" },
filename: "remoteEntry.js",
exposes: {
    './web-components': './src/bootstrap.ts',
},

Bootstrapping

Our bootstrap helper function bootstraps your shell and your micro frontend and takes care of some details needed in a multi-framework/ multi-version scenario (like sharing the platform used).

// main.ts
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
import { bootstrap } from '@angular-architects/module-federation-tools';

bootstrap(AppModule, {
  production: environment.production
});

Use this bootstrap helper for both, your shell and your micro frontends!

Routing to Web Components

The WebComponentWrapper helps you to route to web components:

export const APP_ROUTES: Routes = [
    [...]
    {
        path: 'angular1',
        component: WebComponentWrapper,
        data: {
          remoteEntry: 'https://nice-grass-018f7d910.azurestaticapps.net/remoteEntry.js',
          remoteName: 'angular1',
          exposedModule: './web-components',
          elementName: 'angular1-element'
        } as WebComponentWrapperOptions
    },
    [...]
}

Important: Angular 13+

Beginning with Angular 13, the CLI is emitting EcmaScript modules. Hence, we need to adjust the usage of the WebComponentWrapper when loading a remote that has been created with the CLI 13 or higher. For this, set type to remote and skip the remoteName property (for Modules, we don't need a remoteName):

export const APP_ROUTES: Routes = [
    [...]
    {
        path: 'angular1',
        component: WebComponentWrapper,
        data: {
          type: 'module',
          remoteEntry: 'https://your-path/remoteEntry.js',
          exposedModule: './web-components',
          elementName: 'angular1-element'
        } as WebComponentWrapperOptions
    },
    [...]
}

Sub-Routes

If a web component has it's own router, you can use our UrlMatchers startsWith and endsWith to define, which part of the URL is intended for the shell and for the micro frontend:

// Shell
export const APP_ROUTES: Routes = [
    [...]
    {
        matcher: startsWith('angular3'),
        component: WebComponentWrapper,
        data: {
          remoteEntry: 'https://gray-river-0b8c23a10.azurestaticapps.net/remoteEntry.js',
          remoteName: 'angular3',
          exposedModule: './web-components',
          elementName: 'angular3-element'
        } as WebComponentWrapperOptions
    },
    [...]
}
// Micro Frontend
export const APP_ROUTES: Routes = [
    [...]
    { matcher: endsWith('a'), component: AComponent},
    { matcher: endsWith('b'), component: BComponent},
    [...]
}

In order to prevent issues with the "inner" router, use our helper function connectRouter.

// AppComponent in Micro Frontend
@Component({ ... })
export class AppComponent {

  constructor(private router: Router) { }

  ngOnInit(): void {
    connectRouter(this.router);
  }

}

Directly Loading a Web Component via Module Federation

The WebComponentWrapper can also be used as a traditional component:

<mft-wc-wrapper [options]="item"></mft-wc-wrapper>
item: WebComponentWrapperOptions = {
    remoteEntry: 'https://witty-wave-0a695f710.azurestaticapps.net/remoteEntry.js',
    remoteName: 'react',
    exposedModule: './web-components',
    elementName: 'react-element'
}, 

The optional properties props and events allow to defined properties and events for the web component:

props = {
    "message": "Hello from Shell"
}

events = {
    "clicked": (event) => {
        console.debug('clicked!', event);
    }
}
<mft-wc-wrapper [options]="item" [props]="props" [events]="events"></mft-wc-wrapper>

Sharing Zone.js

In order to share zone.js, call our shareNgZone helper when starting the shell.

import { Component, NgZone } from '@angular/core';
import { shareNgZone } from '@angular-architects/module-federation-tools';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
})
export class AppComponent {
  title = 'shell';

  constructor(private ngZone: NgZone) {
    shareNgZone(ngZone);
  }

}

The micro frontends will pick it up, if they are bootstrapped with the bootstrap helper (see above).

More about the underlying ideas

Please find more information on the underlying ideas in this blog article.

FAQs

Package last updated on 17 Dec 2021

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc