Upgrading React with micro-frontends

Alex O'Callaghan

マイクロフロントエンドでReactをアップグレードする

原文は Alex O'Callaghan により に公開されました。 このブログを購読する

2021年、私たちはReact 17を使ってマイクロフロントエンドアーキテクチャを導入しました。推奨に従い、reactreact-domを共有のシングルトンモジュールとして設定し、アプリ全体を単一のReactツリーでレンダリングしていました。多くの人気ライブラリがReact 18を必須とするようになり、さらにReact 19も間近に迫る中で、マイクロフロントエンドのReactをアップグレードする必要が出てきました。多くのチームが関わっているため、段階的に少しずつ進める必要があります。

ブリッジコンポーネントの導入

2026年追記その後、私たちは独自のマイクロフロントエンド向けReactブリッジパッケージをオープンソース化しました。詳細はOpen sourcing our microfrontend React bridgeをご覧ください。本記事では、@module-federation/bridge-reactパッケージを使った当初の手法について説明します。

マイクロフロントエンドを別のReactツリーでレンダリングするために、「ブリッジ」コンポーネントのラッパーを追加しました。これにより、シェルに影響を与えることなくマイクロフロントエンド側でReactをアップグレードできるようになります。

@module-federation/bridge-reactパッケージは、このアプローチを支援するヘルパーを提供しています。マイクロフロントエンド内に新しいexport-app.tsxファイルを追加し、エントリーポイントのReactコンポーネントをブリッジでラップしました:

// src/export-app.tsx
import { createBridgeComponent } from "@module-federation/bridge-react";
import App from "./App";

export default createBridgeComponent({
  rootComponent: App,
});

export const BRIDGE = true;

新しいエントリーファイルを公開するために、ModuleFederationPluginの更新も必要でした。シェルより新しいバージョンにアップグレードするために、reactreact-domをシングルトンとして共有するのをやめる必要がありました。

// webpack.config.js
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      name: "app",
      filename: "remoteEntry.js",
      exposes: {
        "./App": "./src/export-app",
      },
      shared: ["react", "react-dom"],
    }),
  ],
};

シェルアプリケーションでは、import-remoteを使ってremoteEntryファイルを動的に読み込む手法を採用しています。後方互換性を保ちつつ、直接公開されたReactコンポーネントとブリッジ化されたReactコンポーネントの両方を読み込めるように、これを調整する必要があります:

import { createRemoteComponent } from '@module-federation/bridge-react';

const SomeRemote = React.lazy(async () => {
  const remote = await importRemote({
    url: '/bundles/remote-app',
    scope: 'remote-app',
    module: 'App',
  });

  if (remote.BRIDGE) {
    return {
      default: createRemoteComponent({
        loader: () => remote,
        loading: <div>Loading...</div>,
        fallback: (info) =>
          <div>Failed to load {info.error.message}</div>,
      });
    }

    return remote;
  }
});

ここではいくつかのことを行っています:

  • importRemoteを使ってremoteEntry.jsファイルを遅延読み込みしています。これにより、不要なマイクロフロントエンドの読み込みを避けられます。
  • エクスポートされた定数BRIDGEをチェックしています。これはマイクロフロントエンドがブリッジコンポーネントでラップされているかどうかを示します。これにより、各チームがブリッジを使うかどうかを自由に選べ、まだ移行していない場合との互換性も保たれます。
  • ブリッジコンポーネントをdefaultプロパティを持つオブジェクトで返すことで、React.lazyが受け取ることを想定している動的に読み込まれたモジュールの形状を再現しています。

これらの変更により、シェルをアップグレードすることなく、個々のマイクロフロントエンドをReact 18にアップグレードできるようになります。すべてのマイクロフロントエンドがブリッジ方式を採用すれば、今度はマイクロフロントエンドをアップグレードすることなくシェルをアップグレードできるようになります。

この記事は「muse-spark-1.2-contributor」を使用して翻訳されました。

コメント