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 模式下。

指定包版本

有三种方法可以指定共享库的版本。

数组语法

此语法允许您仅使用包名称共享库。这种方法适用于原型制作,但它不允许您扩展到大型生产环境,因为像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

布尔值

此提示将允许 webpack 直接包含提供的和后备模块,而不是通过异步请求获取库。换句话说,这允许在初始块中使用此共享模块。此外,请注意,启用此提示后,将始终下载所有提供的和后备模块。

import

false | 字符串

应放置在共享范围内的提供的模块。如果在共享范围中找不到共享模块或版本无效,此提供的模块还充当后备模块。(此提示的值默认为属性名称。)

packageName

字符串

用于从描述文件中确定所需版本的包名称。仅当无法从请求中自动确定包名称时才需要此项。

requiredVersion

false | 字符串

包的所需版本。它接受语义版本控制。例如,“^1.2.3”。

shareKey

字符串

请求的共享模块在此键下从共享范围中查找。

shareScope

字符串

共享作用域的名称。

singleton

布尔值

此提示仅允许共享作用域中共享模块的单个版本(默认情况下禁用)。某些库使用全局内部状态(例如 react、react-dom)。因此,一次仅运行该库的一个实例至关重要。

在共享作用域中存在同一依赖项的多个版本的情况下,将使用最高语义版本。

strictVersion

布尔值

如果版本无效,此提示允许 webpack 拒绝共享模块(当本地后备模块可用且共享模块不是单例时,默认为 true,否则为 false,如果没有指定所需版本,则不起作用)。如果找不到所需版本,则会引发运行时错误。

version

false | 字符串

提供的模块的版本。它允许 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