Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(mf2): add shareStrategy #7651

Merged
merged 2 commits into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import React from "react";

export default () => {
return `App rendered with [${React()}]`;
};
Original file line number Diff line number Diff line change
@@ -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");

});
});

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -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",
}
}
})
]
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/** @type {import("../../../..").TConfigCaseConfig} */
module.exports = {
findBundle: function (i, options) {
return "./main.js";
}
};
2 changes: 2 additions & 0 deletions packages/rspack/etc/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -6204,6 +6204,8 @@ export interface ModuleFederationPluginOptions extends Omit<ModuleFederationPlug
implementation?: string;
// (undocumented)
runtimePlugins?: RuntimePlugins;
// (undocumented)
shareStrategy?: "version-first" | "loaded-first";
}

// @public (undocumented)
Expand Down
4 changes: 4 additions & 0 deletions packages/rspack/src/container/ModuleFederationPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export interface ModuleFederationPluginOptions
extends Omit<ModuleFederationPluginV1Options, "enhanced"> {
runtimePlugins?: RuntimePlugins;
implementation?: string;
shareStrategy?: "version-first" | "loaded-first";
}
export type RuntimePlugins = string[];

Expand Down Expand Up @@ -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}`;
Expand Down
8 changes: 7 additions & 1 deletion packages/rspack/src/container/default.runtime.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 ||
Expand Down Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
10 changes: 10 additions & 0 deletions website/docs/en/plugins/webpack/module-federation-plugin.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -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'`
2heal1 marked this conversation as resolved.
Show resolved Hide resolved

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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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` 字段。
10 changes: 10 additions & 0 deletions website/docs/zh/plugins/webpack/module-federation-plugin.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,16 @@ module.exports = {

定义当前应用共享依赖的命名空间。通过在不同的应用之间配置命名空间,可以控制模块的共享行为,包括确定哪些模块在不同的应用之间是共享的。默认的命名空间为 `"default"`。

### shareScope

- 类型:`'version-first' | 'loaded-first'`
2heal1 marked this conversation as resolved.
Show resolved Hide resolved

控制共享依赖的加载策略:

- `'version-first'`:版本优先。设置后,会自动加载所有 _remotes_ 入口文件,并**注册**对应的共享依赖,确保能获取到所有的共享依赖版本。当对版本有严格要求时,推荐使用此策略。

- `'loaded-first'`:复用优先。设置后,不会自动加载 _remotes_ 入口文件(仅在有需求时才会加载),优先复用已注册的共享依赖。当对版本没有严格要求且对性能有要求时,推荐使用此策略。

### remoteType

- 类型:[`ExternalsType`](/config/externals#externalstype)
Expand Down
Loading