ModuleFederationPlugin

ModuleFederationPlugin 允许在运行时将一个构建的模块提供给其他独立的构建,或者消费其他构建的模块。

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

选项

运行时

创建一个带有指定名称的新运行时 chunk。

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 直接包含提供的模块和回退模块,而不是通过异步请求获取库。换句话说,这允许在初始 chunk 中使用此共享模块。另请注意,启用此提示后,所有提供的模块和回退模块将始终被下载。

import

false | 字符串

应该放置在共享作用域中的提供的模块。如果没有在共享作用域中找到共享模块或版本无效,此提供的模块也作为回退模块。(此提示的值默认为属性名。)

packageName

字符串

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

requiredVersion

false string

此字段指定包的所需版本。它接受语义版本控制,例如 "^1.2.3"。此外,如果版本作为 URL 提供,例如:"git+ssh://git@github.com:foo/bar.git#v1.0.0",它也会检索该版本。

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
        },
      },
    }),
  ],
};

延伸阅读

5 贡献者

XiaofengXie16chenxsanburhanudaychristian24KhaledTaymour