ModuleFederationPlugin

ModuleFederationPlugin を使うと、ビルドは実行時に他の独立したビルドとモジュールを提供または消費できます。

const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      // options' typings in typescript
      runtime: string | false,
    }),
  ],
};

オプション

ランタイム

指定された名前で新しいランタイムチャンクを作成します。

webpack.config.js

const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      runtime: 'my-runtime-name',
    }),
  ],
};

ライブラリの共有

設定の shared キーを使うと、フェデレーションされたモジュール間で共有されるライブラリを定義できます。パッケージ名は、package.json の dependencies セクションにあるものと同じです。ただし、デフォルトでは、webpack はライブラリのルートレベルのみを共有します。

const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      // adds date-fns as shared module
      shared: ['date-fns'],
    }),
  ],
};

したがって、アプリケーションでは次のようなことができます。

import { format } from 'date-fns';

format(new Date(2014, 1, 11), 'MM/dd/yyyy');

webpackは、date-fnsを共有ライブラリとして定義しているすべてのフェデレーションモジュール間で、date-fnsを自動的に共有します。ただし、パッケージのルートレベルにないもの、たとえばdate-fns/locale/en-GB/index.jsにアクセスしたい場合は、shared設定でパッケージ名に/を追加する必要があります。

const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      // adds date-fns as shared module
      // all files of the package will be shared
      shared: ['date-fns/'],
    }),
  ],
};

/構文を使用すると、パッケージのすべてのファイルにアクセスできます。ただし、特にdevelopmentモードではパフォーマンスに影響を与えるため、必要な場合にのみ使用してください。

パッケージバージョンの指定

共有ライブラリのバージョンを指定する方法は3つあります。

配列構文

この構文では、パッケージ名のみでライブラリを共有できます。この方法はプロトタイピングには適していますが、reactreact-domのようなライブラリには追加の要件が必要となるため、大規模な本番環境にスケールすることはできません。

const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      // adds lodash as shared module
      // version is inferred from package.json
      // there is no version check for the required version
      // so it will always use the higher version found
      shared: ['lodash'],
    }),
  ],
};
オブジェクト構文

この構文では、パッケージ名をキーとし、バージョン(semver)を値として定義することで、各共有ライブラリをより詳細に制御できます。

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      shared: {
        // adds lodash as shared module
        // version is inferred from package.json
        // it will use the highest lodash version that is >= 4.17 and < 5
        lodash: '^4.17.0',
      },
    }),
  ],
};
共有ヒント付きオブジェクト構文

この構文では、パッケージ名をキーとして定義し、値を共有動作を変更するためのヒントを含むオブジェクトとして定義することで、各共有パッケージに追加のヒントを提供できます。

const deps = require('./package.json').dependencies;

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      shared: {
        // adds react as shared module
        react: {
          requiredVersion: deps.react,
          singleton: true,
        },
      },
    }),
  ],
};

共有ヒント

eager

boolean

このヒントを使用すると、webpackは、非同期リクエストを介してライブラリをフェッチする代わりに、提供されたモジュールとフォールバックモジュールを直接含めることができます。つまり、この共有モジュールを最初のチャンクで使用できます。また、このヒントが有効になっている場合は、提供されたモジュールとフォールバックモジュールが常にダウンロードされることに注意してください。

import

false | string

共有スコープに配置する必要がある提供されたモジュール。この提供されたモジュールは、共有スコープに共有モジュールが見つからない場合、またはバージョンが無効な場合のフォールバックモジュールとしても機能します。(このヒントの値は、デフォルトでプロパティ名になります。)

packageName

string

記述ファイルから必要なバージョンを決定するために使用されるパッケージ名。これは、リクエストからパッケージ名を自動的に決定できない場合にのみ必要です。

requiredVersion

false | string

パッケージの必須バージョン。セマンティックバージョニングを受け入れます。たとえば、"^1.2.3"など。

shareKey

string

要求された共有モジュールは、共有スコープからこのキーで検索されます。

shareScope

string

共有スコープの名前。

singleton

boolean

このヒントは、共有スコープ内で共有モジュールの単一バージョンのみを許可します(デフォルトでは無効)。一部のライブラリはグローバルな内部状態を使用します(例:react、react-dom)。したがって、一度に実行されるライブラリのインスタンスを1つだけにすることが重要です。

共有スコープに同じ依存関係の複数のバージョンがある場合は、最も高いセマンティックバージョンが使用されます。

strictVersion

boolean

このヒントを使用すると、バージョンが無効な場合にwebpackが共有モジュールを拒否できます(ローカルのフォールバックモジュールが利用可能で、共有モジュールがシングルトンでない場合はデフォルトでtrue、それ以外の場合はfalseです。必須バージョンが指定されていない場合は効果がありません)。必須バージョンが見つからない場合は、ランタイムエラーをスローします。

version

false | string

提供されたモジュールのバージョン。webpackは、より低い一致バージョンを置き換えることができますが、より高いバージョンは置き換えることができません。

デフォルトでは、webpackは依存関係のpackage.jsonファイルからのバージョンを使用します。

追加の例

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      // adds vue as shared module
      // version is inferred from package.json
      // it will always use the shared version, but print a warning when the shared vue is < 2.6.5 or >= 3
      shared: {
        vue: {
          requiredVersion: '^2.6.5',
          singleton: true,
        },
      },
    }),
  ],
};
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      // adds vue as shared module
      // there is no local version provided
      // it will emit a warning if the shared vue is < 2.6.5 or >= 3
      shared: {
        vue: {
          import: false,
          requiredVersion: '^2.6.5',
        },
      },
    }),
  ],
};
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      // adds vue as shared module
      // there is no local version provided
      // it will throw an error when the shared vue is < 2.6.5 or >= 3
      shared: {
        vue: {
          import: false,
          requiredVersion: '^2.6.5',
          strictVersion: true,
        },
      },
    }),
  ],
};
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      shared: {
        'my-vue': {
          // can be referenced by import "my-vue"
          import: 'vue', // the "vue" package will be used as a provided and fallback module
          shareKey: 'shared-vue', // under this name the shared module will be placed in the share scope
          shareScope: 'default', // share scope with this name will be used
          singleton: true, // only a single version of the shared module is allowed
          strictVersion: true, // don't use shared version when version isn't valid. Singleton or modules without fallback will throw, otherwise fallback is used
          version: '1.2.3', // the version of the shared module
          requiredVersion: '^1.0.0', // the required version of the shared module
        },
      },
    }),
  ],
};

4 貢献者

XiaofengXie16chenxsanburhanudaychristian24