From c7ca5aef5c32b812336a667f4ecb1dd104eb5be8 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Thu, 22 Aug 2024 12:00:48 +0800 Subject: [PATCH 1/2] feat(mf2): add shareStrategy --- .../container-1-5/share-strategy/App.js | 5 ++++ .../container-1-5/share-strategy/index.js | 8 +++++++ .../share-strategy/node_modules/react.js | 3 +++ .../share-strategy/rspack.config.js | 23 +++++++++++++++++++ .../share-strategy/test.config.js | 6 +++++ packages/rspack/etc/api.md | 2 ++ .../src/container/ModuleFederationPlugin.ts | 4 ++++ .../rspack/src/container/default.runtime.js | 8 ++++++- .../webpack/module-federation-plugin-v1.mdx | 2 +- .../webpack/module-federation-plugin.mdx | 10 ++++++++ .../webpack/module-federation-plugin-v1.mdx | 2 +- .../webpack/module-federation-plugin.mdx | 10 ++++++++ 12 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 packages/rspack-test-tools/tests/configCases/container-1-5/share-strategy/App.js create mode 100644 packages/rspack-test-tools/tests/configCases/container-1-5/share-strategy/index.js create mode 100644 packages/rspack-test-tools/tests/configCases/container-1-5/share-strategy/node_modules/react.js create mode 100644 packages/rspack-test-tools/tests/configCases/container-1-5/share-strategy/rspack.config.js create mode 100644 packages/rspack-test-tools/tests/configCases/container-1-5/share-strategy/test.config.js diff --git a/packages/rspack-test-tools/tests/configCases/container-1-5/share-strategy/App.js b/packages/rspack-test-tools/tests/configCases/container-1-5/share-strategy/App.js new file mode 100644 index 00000000000..cb616e962d2 --- /dev/null +++ b/packages/rspack-test-tools/tests/configCases/container-1-5/share-strategy/App.js @@ -0,0 +1,5 @@ +import React from "react"; + +export default () => { + return `App rendered with [${React()}]`; +}; diff --git a/packages/rspack-test-tools/tests/configCases/container-1-5/share-strategy/index.js b/packages/rspack-test-tools/tests/configCases/container-1-5/share-strategy/index.js new file mode 100644 index 00000000000..2510854b4ef --- /dev/null +++ b/packages/rspack-test-tools/tests/configCases/container-1-5/share-strategy/index.js @@ -0,0 +1,8 @@ +it("should load the component from container", () => { + return import("./App").then(({ default: App }) => { + expect(App()).toBe("App rendered with [This is react 0.1.2]"); + const shareStrategy = __webpack_require__.federation.initOptions.shareStrategy; + expect(shareStrategy).toBe("loaded-first"); + + }); +}); diff --git a/packages/rspack-test-tools/tests/configCases/container-1-5/share-strategy/node_modules/react.js b/packages/rspack-test-tools/tests/configCases/container-1-5/share-strategy/node_modules/react.js new file mode 100644 index 00000000000..bcf433f2afb --- /dev/null +++ b/packages/rspack-test-tools/tests/configCases/container-1-5/share-strategy/node_modules/react.js @@ -0,0 +1,3 @@ +let version = "0.1.2"; +export default () => `This is react ${version}`; +export function setVersion(v) { version = v; } diff --git a/packages/rspack-test-tools/tests/configCases/container-1-5/share-strategy/rspack.config.js b/packages/rspack-test-tools/tests/configCases/container-1-5/share-strategy/rspack.config.js new file mode 100644 index 00000000000..8b9d4f2139b --- /dev/null +++ b/packages/rspack-test-tools/tests/configCases/container-1-5/share-strategy/rspack.config.js @@ -0,0 +1,23 @@ +const { ModuleFederationPlugin } = require("@rspack/core").container; + +/** @type {import("@rspack/core").Configuration} */ +module.exports = { + output: { + filename: "[name].js", + uniqueName: "share-strategy" + }, + plugins: [ + new ModuleFederationPlugin({ + shareStrategy:'loaded-first', + shared: { + react: { + version: false, + requiredVersion: false, + singleton: true, + strictVersion: false, + version: "0.1.2", + } + } + }) + ] +}; diff --git a/packages/rspack-test-tools/tests/configCases/container-1-5/share-strategy/test.config.js b/packages/rspack-test-tools/tests/configCases/container-1-5/share-strategy/test.config.js new file mode 100644 index 00000000000..9e9c1c26680 --- /dev/null +++ b/packages/rspack-test-tools/tests/configCases/container-1-5/share-strategy/test.config.js @@ -0,0 +1,6 @@ +/** @type {import("../../../..").TConfigCaseConfig} */ +module.exports = { + findBundle: function (i, options) { + return "./main.js"; + } +}; diff --git a/packages/rspack/etc/api.md b/packages/rspack/etc/api.md index d083d73b674..8d3126d559c 100644 --- a/packages/rspack/etc/api.md +++ b/packages/rspack/etc/api.md @@ -6204,6 +6204,8 @@ export interface ModuleFederationPluginOptions extends Omit { runtimePlugins?: RuntimePlugins; implementation?: string; + shareStrategy?: "version-first" | "loaded-first"; } export type RuntimePlugins = string[]; @@ -184,6 +185,9 @@ function getDefaultEntryRuntime( `const __module_federation_container_name__ = ${JSON.stringify( options.name ?? compiler.options.output.uniqueName )}`, + `const __module_federation_share_strategy__ = ${JSON.stringify( + options.shareStrategy ?? "version-first" + )}`, compiler.webpack.Template.getFunctionContent(require("./default.runtime")) ].join(";"); return `@module-federation/runtime/rspack.js!=!data:text/javascript,${content}`; diff --git a/packages/rspack/src/container/default.runtime.js b/packages/rspack/src/container/default.runtime.js index 3cac7700693..a773e520cd6 100644 --- a/packages/rspack/src/container/default.runtime.js +++ b/packages/rspack/src/container/default.runtime.js @@ -2,7 +2,8 @@ var __module_federation_bundler_runtime__, __module_federation_runtime_plugins__, __module_federation_remote_infos__, - __module_federation_container_name__; + __module_federation_container_name__, + __module_federation_share_strategy__; module.exports = function () { if ( (__webpack_require__.initializeSharingData || @@ -83,6 +84,11 @@ module.exports = function () { "name", () => __module_federation_container_name__ ); + early( + __webpack_require__.federation.initOptions, + "shareStrategy", + () => __module_federation_share_strategy__ + ); early(__webpack_require__.federation.initOptions, "shared", () => { const shared = {}; for (let [scope, stages] of Object.entries( diff --git a/website/docs/en/plugins/webpack/module-federation-plugin-v1.mdx b/website/docs/en/plugins/webpack/module-federation-plugin-v1.mdx index 7829aca25ae..52c21006d93 100644 --- a/website/docs/en/plugins/webpack/module-federation-plugin-v1.mdx +++ b/website/docs/en/plugins/webpack/module-federation-plugin-v1.mdx @@ -6,7 +6,7 @@ import { ApiMeta, Stability } from '@components/ApiMeta'; This plugin corresponds to Module Federation v1.0, which is the [ModuleFederationPlugin in webpack](https://webpack.js.org/plugins/module-federation-plugin/). -The configuration is consistent with the ModuleFederationPlugin above, except for the two fields `implementation` and `runtimePlugins`. +The configuration is consistent with the ModuleFederationPlugin above, except for the three fields `implementation`, `runtimePlugins` and `shareStrategy`. ```js new rspack.container.ModuleFederationPluginV1(); diff --git a/website/docs/en/plugins/webpack/module-federation-plugin.mdx b/website/docs/en/plugins/webpack/module-federation-plugin.mdx index 690257310d1..80087bcb6f8 100644 --- a/website/docs/en/plugins/webpack/module-federation-plugin.mdx +++ b/website/docs/en/plugins/webpack/module-federation-plugin.mdx @@ -68,6 +68,16 @@ Define the output format of remote container entry. The default libraryType is " Define the namespace for shared dependencies in the current container. By configuring share scopes between different containers, the sharing behavior of modules can be controlled, including determining which modules are shared between different containers. The default share scope is `"default"`. +### shareStrategy + +- Type: `'version-first' | 'loaded-first'` + +Control the loading strategy of shared dependencies: + +- `'version-first'`: Version takes precedence. After setting, all _remotes_ entry files will be automatically loaded and **register** the corresponding shared dependencies to ensure that all shared dependency versions can be obtained. This strategy is recommended when there are strict version requirements. + +- `'loaded-first'`: reuse first. After setting, the _remotes_ entry file will not be automatically loaded (it will only be loaded when needed), and registered shared dependencies will be reused first. This strategy is recommended when there are no strict requirements on the version and performance is required. + ### remoteType - Type: [`ExternalsType`](/config/externals#externalstype) diff --git a/website/docs/zh/plugins/webpack/module-federation-plugin-v1.mdx b/website/docs/zh/plugins/webpack/module-federation-plugin-v1.mdx index 0b3870f0c4d..4c4fb05a88d 100644 --- a/website/docs/zh/plugins/webpack/module-federation-plugin-v1.mdx +++ b/website/docs/zh/plugins/webpack/module-federation-plugin-v1.mdx @@ -28,4 +28,4 @@ module.exports = { }; ``` -ModuleFederationPluginV1 的配置基本与 [ModuleFederationPlugin](https://github.com/plugins/webpack/module-federation-plugin) 相同,但不支持 `implementation` 和 `runtimePlugins` 字段。 +ModuleFederationPluginV1 的配置基本与 [ModuleFederationPlugin](https://github.com/plugins/webpack/module-federation-plugin) 相同,但不支持 `implementation` 、 `runtimePlugins` 、`shareStrategy` 字段。 diff --git a/website/docs/zh/plugins/webpack/module-federation-plugin.mdx b/website/docs/zh/plugins/webpack/module-federation-plugin.mdx index 3ecf9b2e120..7c42f9a2557 100644 --- a/website/docs/zh/plugins/webpack/module-federation-plugin.mdx +++ b/website/docs/zh/plugins/webpack/module-federation-plugin.mdx @@ -68,6 +68,16 @@ module.exports = { 定义当前应用共享依赖的命名空间。通过在不同的应用之间配置命名空间,可以控制模块的共享行为,包括确定哪些模块在不同的应用之间是共享的。默认的命名空间为 `"default"`。 +### shareScope + +- 类型:`'version-first' | 'loaded-first'` + +控制共享依赖的加载策略: + +- `'version-first'`:版本优先。设置后,会自动加载所有 _remotes_ 入口文件,并**注册**对应的共享依赖,确保能获取到所有的共享依赖版本。当对版本有严格要求时,推荐使用此策略。 + +- `'loaded-first'`:复用优先。设置后,不会自动加载 _remotes_ 入口文件(仅在有需求时才会加载),优先复用已注册的共享依赖。当对版本没有严格要求且对性能有要求时,推荐使用此策略。 + ### remoteType - 类型:[`ExternalsType`](/config/externals#externalstype) From be82b20e95c1265fddc745617021f38068b44ab1 Mon Sep 17 00:00:00 2001 From: "zhanghang.heal" Date: Thu, 22 Aug 2024 14:15:17 +0800 Subject: [PATCH 2/2] chore: update api.md --- packages/rspack/etc/api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/rspack/etc/api.md b/packages/rspack/etc/api.md index 8d3126d559c..3f8d793455b 100644 --- a/packages/rspack/etc/api.md +++ b/packages/rspack/etc/api.md @@ -6205,7 +6205,7 @@ export interface ModuleFederationPluginOptions extends Omit