@ama-mfe/ng-utils

中文文档
15.3.1发布于 2026/11/10BSD-3-ClauseTypeScriptES Module构建来源已验证近 30 天下载 4982

@ama-mfe/ng-utils is an Angular library designed to streamline communication within a micro-frontend architecture that uses iframes. This package is built on the [Amadeus Toolkit for Micro Frontends framework](https://www.npmjs.com/package/@amadeus-it-g

原始使用文档
文档目录11 节
  1. Installation
  2. Consumer and Producer
  3. How to use
  4. Connection to the communication service
  5. Enable a message-based feature
  6. Write your own producer and consumers.
  7. Iframe Embed Component
  8. Host information
  9. Browser history handling
  10. User Activity Tracking
  11. Navigation Exit

Ama MFE Angular Utils

@ama-mfe/ng-utils is an Angular library designed to streamline communication within a micro-frontend architecture that uses iframes. This package is built on the Amadeus Toolkit for Micro Frontends framework and offers a suite of tools - including helpers, wrappers, and services - to facilitate seamless integration and interaction between host and embedded applications.

Key features include:

  • Connect: Connect to the communication protocol and send messages to registered applications.
  • Navigation: Handles navigation messages between the host and embedded applications. Embedded applications can use RoutingService to sync their internal routing with the host application. The host application can use NavigationConsumerService to get notifications about navigation events in the embedded applications.
  • Navigation Exit: Negotiates navigation when an embedded module holds unsaved work. Modules report their block state, and either side asks for confirmation before navigation proceeds.
  • Theme: Allows the application of unified CSS variables and styles across embedded modules, ensuring a cohesive look and feel.
  • Resize: Dynamically adjusts the iframe dimensions to fit the content of the embedded application, enhancing the user experience.
  • User Activity: Tracks user interactions across embedded micro-frontends for session timeout functionality, analytics, or any feature that needs to detect user activity.
  • Iframe Embed: A ready-to-use Angular component that renders an iframe with all MFE integration directives pre-wired (connect, scalable, host info, theme).

Installation

To install the package, run:

npm exec ng add @ama-mfe/ng-utils

Consumer and Producer

In the communication protocol, a message is created by a Producer and sent to a Consumer which will read the message and react according to its content.

The @ama-mfe/ng-utils package exposes a set of features based on messages exchanged between a host application and its embedded module. For each feature, the package provides a Producer/Consumer pair. The former service is in charge of delivering the messages based on triggers (resize event, call to a public function etc.) while the latter implements the logic behind the feature (resizing of the iframe, application of a theme, etc.).

How to use

Connection to the communication service

Configure your application connection

Applications first need to provide and configure the ConnectionService to use the communication protocol. The provideConnection method allows an application to register with a unique ID that others will use to connect and target the application.

import {provideConnection} from '@ama-mfe/ng-utils';

export const appConfig: ApplicationConfig = {
  providers: [
    provideConnection({
      id: 'applicationUniqueID'
    })
  ]
};

Initiate the communication with the host application

An application embedded into another one can connect to its host using the [ConnectionService]. To establish the connection, the embedded application requires the host application id (set via the connection service's provider).

// main.ts
import {inject, runInInjectionContext} from '@angular/core';
import {bootstrapApplication} from '@angular/platform-browser';
import {ConnectionService, NavigationConsumerService} from '@ama-mfe/ng-utils';

bootstrapApplication(App, appConfig)
  .then((m) => {
    runInInjectionContext(m.injector, () => {
      if (window.top !== window.self) {
        // If embedded in an iframe, connect to the host
        inject(ConnectionService).connect('hostUniqueID');
      }
      // Other injections
    })
  });

Initiate the connection to your embedded module

The recommended way to embed a module is to use the IframeEmbedComponent, which pre-wires connect, scalable, hostInfo and applyTheme on the iframe:

<mfe-iframe-embed
  src="https://my-embedded-app.example.com"
  moduleId="myModuleUniqueID"
  hostApplicationId="hostUniqueID" />

Alternatively, if you need full control over the iframe, you can use the connect directive directly. The communication pipe will be closed once the iframe is destroyed.

<iframe [src]='myModuleUrl'
        [connect]='myModuleUniqueID'>
</iframe>

In this example, myModuleUniqueID refers to the id provided in the provideConnection method.

Enable a message-based feature

To use a feature based on the message communication protocol, you need first to identify if your application will be a user of the message (Consumer) or the one sending the message (Producer). This may depend on the context and the type of message. For instance, an application can be the consumer of navigation messages but the producer of theme messages.

Consumers

If you are a consumer of the message, call the start and stop methods to respectively enable and disable the feature.

import {Component, inject} from '@angular/core';
import {NavigationConsumerService} from '@ama-mfe/ng-utils';
import {ThemeConsumerService} from "./theme-consumer-service";

@Component({
  selector: 'app-example-module-component',
  template: './example-module-component.html',
  styleUrl: './example-module-component.scss',
})
export class ExampleModuleComponent {
  private readonly navigationConsumerService = inject(NavigationConsumerService);

  constructor() {
    this.navigationConsumerService.start();
  }

  ngOnDestroy() {
    this.navigationConsumerService.stop()
  }
}

Depending on your use case, you might need to start the service as soon as your application start running. In this case, you may inject it in the main.ts:

// main.ts
import {inject, runInInjectionContext} from '@angular/core';
import {bootstrapApplication} from '@angular/platform-browser';
import {ConnectionService, ThemeConsumerService} from '@ama-mfe/ng-utils';

bootstrapApplication(App, appConfig)
  .then((m) => {
    runInInjectionContext(m.injector, () => {
      if (window.top !== window.self) {
        // If embedded in an iframe, connect to the host
        inject(ConnectionService).connect('hostUniqueID');
        // Start the service to consume messages
        inject(ThemeConsumerService).start();
      }
      // Other injections
    })
  });

Producers

If your application is a producer, just inject the message producer service and call the trigger when needed. There is no standardization on the name of the methods used to trigger a message. It will be different for each service.

Services provided in @ama-mfe/ng-utils

You will find more information for each service in their respective README.md:

Write your own producer and consumers.

Use the ProducerManagerService and the ConsumerManagerService to support your own custom messages.

A message should be identified by its type and a version to allow different message versions between the host and the embedded applications (and avoid migration issues).

import type {Message} from '@amadeus-it-group/microfrontends';

export interface CustomMessageV1_0 extends Message {
  type: 'custom',
  version: '1.0',
  // Custom properties
  customPayload: any
}
// Use union type here to add all the future version
// For example CustomMessage = CustomMessageV1_0 | CustomMessagev2_0
export type CustomMessageVersions = CustomMessageV1_0;

Message version compatibility

The ConsumerManagerService dispatches incoming messages with a semver-compatible fallback, applied uniformly to every message type in this package (navigation, theme, resize, user-activity, history, and custom messages).

Within a major version, a consumer's highest declared minor ≤ the incoming minor, is used. This lets producers add optional fields in a new minor version (e.g. v1.1) without breaking consumers that only implement v1.0 — the older handler runs and simply ignores the unknown fields.

Majors are isolated — no cross-major fallback in either direction:

  • An incoming v2.x will never fall back to a v1.x handler (breaking changes are expected across majors).
  • A consumer declaring only v2.x will not match an incoming v1.x (the consumer is ahead of the producer).

Both cross-major cases produce a version_mismatch error. Introducing a new major version therefore requires coordinated updates on both the producer and consumer sides.

Consumer

A consumer should implement the MessageConsumer interface and inject the ConsumeManagerService which handles the registration to the communication protocol. It should list the supported versions and map its callback function in a supportedVersions public object.

import type {CustomMessageV1_0, CustomMessageVersions} from '@ama-mfe/messages';
import type {RoutedMessage} from '@amadeus-it-group/microfrontends';
import {DestroyRef, inject, Injectable} from '@angular/core';
import {ConsumerManagerService, type MessageConsumer} from '@ama-mfe/ng-utils';

@Injectable({
  providedIn: 'root'
})
export class CustomConsumerService implements MessageConsumer<CustomMessageVersions> {
  /**
   * The type of messages this service handles ('custom').
   */
  public readonly type = 'custom';

  /**
   * The supported versions of theme messages and their handlers.
   */
  public readonly supportedVersions = {
    '1.0': (message: RoutedMessage<CustomMessageV1_0>) => console.log('Do some stuff with this message version', message)
  };

  private readonly consumerManagerService = inject(ConsumerManagerService);

  constructor() {
    this.start();
    inject(DestroyRef).onDestroy(() => this.stop());
  }

  /**
   * Starts the theme handler service by registering it into the consumer manager service.
   */
  public start() {
    this.consumerManagerService.register(this);
  }

  /**
   * Stops the theme handler service by unregistering it from the consumer manager service.
   */
  public stop() {
    this.consumerManagerService.unregister(this);
  }
}
Using AbstractMessageConsumer

As a shortcut, custom consumers can extend AbstractMessageConsumer, which already injects the ConsumerManagerService, provides default start/stop implementations, and unregisters automatically when the host injection context is destroyed.

The consumer is not started automatically: define it without a constructor and let the application start it explicitly (typically via provideAppInitializer), exactly like the other consumers above.

@Injectable({ providedIn: 'root' })
export class CustomConsumerService extends AbstractMessageConsumer<CustomMessageVersions> {
  public readonly type = 'custom';
  public readonly supportedVersions = {
    '1.0': (message: RoutedMessage<CustomMessageV1_0>) => { /* ... */ }
  };
}
// app.config.ts
import {inject, provideAppInitializer} from '@angular/core';
import {CustomConsumerService} from './custom-consumer.service';

export const appConfig: ApplicationConfig = {
  providers: [
    provideAppInitializer(() => { inject(CustomConsumerService).start(); })
  ]
};

Note: consumers shipped by @ama-mfe/ng-utils (e.g. NavigationConsumerService, ThemeConsumerService, HistoryConsumerService, ResizeConsumerService) still auto-start from their constructor for backwards compatibility, but this is deprecated and will be removed in v15. Start them explicitly from your application configuration instead. The migration-v14_5 schematic wires the start() calls for you on ng update.

Producer

A producer should implement the MessageProducer interface and inject the ProducerManagerService which handles the registration to the communication protocol. Once connected, it is able to send messages via the MessagePeerService.

import type {CustomMessageV1_0, CustomMessageVersions} from '../messages';
import {MessagePeerService} from '@amadeus-it-group/microfrontends-angular';
import {inject, Injectable} from '@angular/core';
import {type MessageProducer, type ErrorContent, registerProducer} from '@ama-mfe/ng-utils';

@Injectable({
  providedIn: 'root'
})
export class CustomService implements MessageProducer<CustomMessageVersions> {
  private readonly messageService = inject(MessagePeerService<CustomMessageVersions>);

  constructor() {
    registerProducer(this);
  }

  public handleError(message: ErrorContent<CustomMessage_V1_0>): void {
    // If available, use your own logger
    console.error('Error in custom service message', message);
  }

  public postMessageAction(payload: any): void {
    const messageV10 = {
        type: 'custom',
        version: '1.0',
        customPayload: 'test'
      } satisfies CustomMessageV1_0;
    this.messageService.send(messageV10);
  }
}

Iframe Embed Component

The IframeEmbedComponent is a ready-to-use component that renders an iframe with all MFE integration directives pre-configured. It handles URL sanitization, cross-iframe communication (connect), auto-resizing (scalable), host info injection (hostInfo) and theming (applyTheme).

import {IframeEmbedComponent} from '@ama-mfe/ng-utils';

@Component({
  selector: 'app-host',
  imports: [IframeEmbedComponent],
  template: `
    <mfe-iframe-embed
      src="https://my-embedded-app.example.com"
      moduleId="my-module-id"
      hostApplicationId="host-app-id"
      sandbox="allow-scripts allow-same-origin"
      allow="camera; microphone" />
  `
})
export class HostComponent {}
InputTypeDescription
srcstring | SafeResourceUrlThe URL for the iframe. Plain strings are automatically sanitized.
moduleIdstringUnique identifier for the embedded module (used by the connect directive).
hostApplicationIdstringThe host application identifier sent to the embedded module via hostInfo.
sandboxstringThe iframe sandbox permissions. Defaults to 'allow-scripts allow-same-origin'.
allowstringThe iframe Permissions Policy (e.g. 'camera; microphone'). Defaults to '' (attribute not set).

The sandbox and allow attributes are set once at initialization for security reasons (runtime changes are ignored).

Host information

Host application

A host application can send information to the embedded applications using parameters in the URL.

The IframeEmbedComponent handles this automatically via its moduleId and hostApplicationId inputs — no extra setup is needed.

If you manage the iframe yourself, you can apply the hostInfo pipe directly:

<iframe [src]="'myModuleUrl' | hostInfo: {hostId: 'host-app-id', moduleId: 'my-module-to-embed'}"></iframe>

This will add the location.origin and the application id of the host to the URL of the embedded application.

Embedded application

The embedded application can access the data sent in the previous section using an injection token:

import {inject} from '@angular/core';
import {getHostInfo, isEmbedded} from '@ama-mfe/ng-utils';

export class SomeClass {
  private readonly hostInfo = getHostInfo();

  doSomething() {
    if (this.hostInfo.applicationId === 'app1') {
      // Do something when embedded in app1
    } else if (isEmbedded()) {
      // Do something when embedded elsewhere
    } else {
      // Do something when standalone
    }
  }
}

The host information is stored in session storage so it won't be lost when navigating inside the iframe.

Browser history handling

When using iframes to embed applications, the browser history might be shared by the main page and the embedded iframe. For example <iframe src="https://example.com" sandbox="allow-same-origin"> will share the same history as the main page. This can lead to unexpected behavior when using browser 'back' and 'forward' buttons.

To avoid this, the @ama-mfe/ng-utils will forbid the application running in the iframe to alter the browser history. It will happen when connection is configured using provideConection() function. This will prevent the iframe to be able to use the history.pushState and history.replaceState methods.

User Activity Tracking

The User Activity Tracking feature allows a host application (shell) to monitor user interactions across embedded micro-frontends. This is useful for implementing session timeout functionality, analytics, or any feature that needs to know when users are actively interacting with the application.

For detailed documentation, configuration options, and examples, see the User Activity README.

Navigation Exit

The Navigation Exit feature negotiates navigation when an embedded module holds unfinished work (e.g. a dirty form). Both shell- and module-initiated navigations are covered, with the shell owning the confirmation UI and modules running any cleanup the shell asks for before the navigation proceeds.

For the full message contract, services, guards, flows, and integration steps, see the Navigation Exit README.

版本与发布记录

@ama-mfe/ng-utils 共发布 1,045 个版本,首次发布于 2025/03/05;过去 12 个月发布了 547 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
15.3.1latest2026/11/10今天
15.4.0-prerelease.92026/11/091 天前
15.4.0-prerelease.82026/11/073 天前
15.4.0-prerelease.72026/11/073 天前
15.3.0-rc.2rc2026/11/064 天前
15.4.0-prerelease.62026/11/064 天前

其他发布通道:v12-updated → 12.4.25,next → 14.0.0-next.14,v13-updated → 13.5.13,v14-updated → 14.5.4,v15-updated → 15.1.3,rc → 15.3.0-rc.2。

关于 @ama-mfe/ng-utils 的常见问题

@ama-mfe/ng-utils 是什么?

@ama-mfe/ng-utils is an Angular library designed to streamline communication within a micro-frontend architecture that uses iframes. This package is built on the [Amadeus Toolkit for Micro Frontends framework](https://www.npmjs.com/package/@amadeus-it-g

如何安装 @ama-mfe/ng-utils?

在项目目录运行 npm install @ama-mfe/ng-utils,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:rxjs(^7.8.1)、@angular/core(^22.0.0)、@angular/common(^22.0.0)、@angular/router(^22.0.0)、@angular/platform-browser(^22.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@ama-mfe/ng-utils 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@ama-mfe/ng-utils 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@ama-mfe/ng-utils 可以商用吗?

@ama-mfe/ng-utils 使用 BSD-3-Clause 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。另外不得用原作者名义为衍生产品背书。以上为概括,不构成法律意见,请以许可原文为准。

@ama-mfe/ng-utils 的下载量有多少?

根据 npm 官方下载统计,@ama-mfe/ng-utils 在 2026/10/06 – 2026/11/04 这 30 天内被下载 4,982 次,日均约 166 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@ama-mfe/ng-utils 还在维护吗?

最新版本 15.3.1 发布于 2026/11/10(今天);至今共发布 1045 个版本,其中过去 12 个月发布了 547 个;首次发布于 2025/03/05。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。