@module-federation/rsbuild-plugin 2.0.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +47 -0
- package/dist/cli/index.js +59 -13
- package/dist/cli/index.mjs +60 -14
- package/dist/utils/ssr.js +35 -12
- package/dist/utils/ssr.mjs +35 -12
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -34,6 +34,53 @@ export default defineConfig({
|
|
|
34
34
|
});
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
+
### Rsbuild App SSR (Node target with custom environment)
|
|
38
|
+
|
|
39
|
+
Use `target: 'node'` with an explicit `environment` to apply federation to a
|
|
40
|
+
specific Rsbuild app environment (for example `ssr`).
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import { pluginModuleFederation } from '@module-federation/rsbuild-plugin';
|
|
44
|
+
import { defineConfig } from '@rsbuild/core';
|
|
45
|
+
|
|
46
|
+
export default defineConfig({
|
|
47
|
+
environments: {
|
|
48
|
+
client: {},
|
|
49
|
+
ssr: {},
|
|
50
|
+
},
|
|
51
|
+
plugins: [
|
|
52
|
+
pluginModuleFederation(
|
|
53
|
+
{
|
|
54
|
+
name: 'host',
|
|
55
|
+
remotes: {
|
|
56
|
+
remote: 'remote@http://localhost:3001/mf-manifest.json',
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
target: 'node',
|
|
61
|
+
environment: 'ssr',
|
|
62
|
+
},
|
|
63
|
+
),
|
|
64
|
+
],
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`target: 'dual'` support remains scoped to Rslib/Rspress workflows.
|
|
69
|
+
|
|
70
|
+
### Default environment detection
|
|
71
|
+
|
|
72
|
+
If `environment` is omitted, the plugin will choose a default per tool:
|
|
73
|
+
|
|
74
|
+
- **Rslib**: `mf`
|
|
75
|
+
- **Rsbuild app**:
|
|
76
|
+
- `target: 'web'` → `web`
|
|
77
|
+
- `target: 'node'` → `node`
|
|
78
|
+
- **Rspress**:
|
|
79
|
+
- `target: 'web'` → `web`
|
|
80
|
+
- `target: 'node'` → `node`
|
|
81
|
+
|
|
82
|
+
You can still override with `environment` when your project uses custom names.
|
|
83
|
+
|
|
37
84
|
### Rslib Module
|
|
38
85
|
|
|
39
86
|
```js
|
package/dist/cli/index.js
CHANGED
|
@@ -97,6 +97,23 @@ const LIB_FORMAT = [
|
|
|
97
97
|
'modern-module'
|
|
98
98
|
];
|
|
99
99
|
const DEFAULT_MF_ENVIRONMENT_NAME = 'mf';
|
|
100
|
+
const DEFAULT_WEB_ENVIRONMENT_NAME = 'web';
|
|
101
|
+
const DEFAULT_NODE_ENVIRONMENT_NAME = 'node';
|
|
102
|
+
const resolveDefaultEnvironmentName = ({ callerName, target })=>{
|
|
103
|
+
if (callerName === external_constant_js_namespaceObject.CALL_NAME_MAP.RSLIB) {
|
|
104
|
+
return DEFAULT_MF_ENVIRONMENT_NAME;
|
|
105
|
+
}
|
|
106
|
+
if (callerName === external_constant_js_namespaceObject.CALL_NAME_MAP.RSPRESS) {
|
|
107
|
+
if (target === 'node') {
|
|
108
|
+
return DEFAULT_NODE_ENVIRONMENT_NAME;
|
|
109
|
+
}
|
|
110
|
+
return DEFAULT_WEB_ENVIRONMENT_NAME;
|
|
111
|
+
}
|
|
112
|
+
if (target === 'node') {
|
|
113
|
+
return DEFAULT_NODE_ENVIRONMENT_NAME;
|
|
114
|
+
}
|
|
115
|
+
return DEFAULT_WEB_ENVIRONMENT_NAME;
|
|
116
|
+
};
|
|
100
117
|
function isStoryBook(rsbuildConfig) {
|
|
101
118
|
var _rsbuildConfig_plugins;
|
|
102
119
|
if ((_rsbuildConfig_plugins = rsbuildConfig.plugins) === null || _rsbuildConfig_plugins === void 0 ? void 0 : _rsbuildConfig_plugins.find((p)=>p && 'name' in p && p.name === 'module-federation-storybook-plugin')) {
|
|
@@ -123,7 +140,10 @@ const isRspressSSGConfig = (bundlerConfigName)=>{
|
|
|
123
140
|
const pluginModuleFederation = (moduleFederationOptions, rsbuildOptions)=>({
|
|
124
141
|
name: RSBUILD_PLUGIN_MODULE_FEDERATION_NAME,
|
|
125
142
|
setup: (api)=>{
|
|
126
|
-
|
|
143
|
+
if (!(moduleFederationOptions === null || moduleFederationOptions === void 0 ? void 0 : moduleFederationOptions.name)) {
|
|
144
|
+
throw new Error('The module federation option "name" is required in @module-federation/rsbuild-plugin.');
|
|
145
|
+
}
|
|
146
|
+
const { target = 'web', ssr = undefined, ssrDir = external_utils_js_namespaceObject.SSR_DIR, environment: configuredEnvironment } = rsbuildOptions || {};
|
|
127
147
|
if (ssr) {
|
|
128
148
|
throw new Error("The `ssr` option is deprecated. If you want to enable SSR, please use `target: 'dual'` instead.");
|
|
129
149
|
}
|
|
@@ -135,6 +155,10 @@ const pluginModuleFederation = (moduleFederationOptions, rsbuildOptions)=>({
|
|
|
135
155
|
const isRslib = callerName === external_constant_js_namespaceObject.CALL_NAME_MAP.RSLIB;
|
|
136
156
|
const isRspress = callerName === external_constant_js_namespaceObject.CALL_NAME_MAP.RSPRESS;
|
|
137
157
|
const isSSR = target === 'dual';
|
|
158
|
+
const environment = configuredEnvironment ?? resolveDefaultEnvironmentName({
|
|
159
|
+
callerName,
|
|
160
|
+
target
|
|
161
|
+
});
|
|
138
162
|
if (isSSR && !isStoryBook(originalRsbuildConfig)) {
|
|
139
163
|
var _rsbuildConfig_environments;
|
|
140
164
|
if (!isRslib && !isRspress) {
|
|
@@ -206,8 +230,14 @@ const pluginModuleFederation = (moduleFederationOptions, rsbuildOptions)=>({
|
|
|
206
230
|
});
|
|
207
231
|
}
|
|
208
232
|
} else if (target === 'node') {
|
|
209
|
-
|
|
210
|
-
(
|
|
233
|
+
var _config_environments2;
|
|
234
|
+
const nodeTargetEnv = (_config_environments2 = config.environments) === null || _config_environments2 === void 0 ? void 0 : _config_environments2[environment];
|
|
235
|
+
if (!nodeTargetEnv) {
|
|
236
|
+
const availableEnvironments = Object.keys(config.environments || {});
|
|
237
|
+
const availableEnvironmentsLabel = availableEnvironments.length > 0 ? availableEnvironments.join(', ') : '(none)';
|
|
238
|
+
throw new Error(`Can not find environment '${environment}' when using target: 'node'. Available environments: ${availableEnvironmentsLabel}.`);
|
|
239
|
+
}
|
|
240
|
+
(0,ssr_js_namespaceObject.patchToolsTspack)(nodeTargetEnv, (config, { environment })=>{
|
|
211
241
|
config.target = 'async-node';
|
|
212
242
|
});
|
|
213
243
|
}
|
|
@@ -284,7 +314,22 @@ const pluginModuleFederation = (moduleFederationOptions, rsbuildOptions)=>({
|
|
|
284
314
|
throw new Error('Can not get bundlerConfigs!');
|
|
285
315
|
}
|
|
286
316
|
bundlerConfigs.forEach((bundlerConfig)=>{
|
|
287
|
-
|
|
317
|
+
const bundlerConfigName = bundlerConfig.name || '';
|
|
318
|
+
const isConfiguredEnvironmentConfig = bundlerConfigName === environment;
|
|
319
|
+
const isNodeTargetEnvironmentConfig = target === 'node' && bundlerConfigName === environment;
|
|
320
|
+
const isRspressSSGEnvironmentConfig = isRspressSSGConfig(bundlerConfig.name);
|
|
321
|
+
const isActiveRspressSSGEnvironmentConfig = isRspress && isRspressSSGEnvironmentConfig;
|
|
322
|
+
const shouldUseSSRPluginConfig = isSSRConfig(bundlerConfig.name) || isNodeTargetEnvironmentConfig;
|
|
323
|
+
if (target === 'node' && !isNodeTargetEnvironmentConfig && !isActiveRspressSSGEnvironmentConfig) {
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
326
|
+
// For non-node targets, scope each plugin instance to its configured
|
|
327
|
+
// environment plus explicit SSR/SSG environments. This prevents a
|
|
328
|
+
// browser-targeted instance from mutating SSR configs.
|
|
329
|
+
if (target !== 'node' && !isConfiguredEnvironmentConfig && !shouldUseSSRPluginConfig && !isActiveRspressSSGEnvironmentConfig) {
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
if (!isMFFormat(bundlerConfig) && !isRspress && !isNodeTargetEnvironmentConfig) {
|
|
288
333
|
return;
|
|
289
334
|
} else if (isStoryBook(originalRsbuildConfig)) {
|
|
290
335
|
bundlerConfig.output.uniqueName = `${moduleFederationOptions.name} -storybook - host`;
|
|
@@ -292,7 +337,8 @@ const pluginModuleFederation = (moduleFederationOptions, rsbuildOptions)=>({
|
|
|
292
337
|
var _bundlerConfig_optimization, _bundlerConfig_optimization1, _bundlerConfig_output, _bundlerConfig_output1, _bundlerConfig_output2;
|
|
293
338
|
// mf
|
|
294
339
|
(0,external_utils_js_namespaceObject.autoDeleteSplitChunkCacheGroups)(moduleFederationOptions, bundlerConfig === null || bundlerConfig === void 0 ? void 0 : (_bundlerConfig_optimization = bundlerConfig.optimization) === null || _bundlerConfig_optimization === void 0 ? void 0 : _bundlerConfig_optimization.splitChunks);
|
|
295
|
-
(0,external_utils_js_namespaceObject.addDataFetchExposes)(moduleFederationOptions.exposes,
|
|
340
|
+
(0,external_utils_js_namespaceObject.addDataFetchExposes)(moduleFederationOptions.exposes, shouldUseSSRPluginConfig);
|
|
341
|
+
const ssrModuleFederationOptions = shouldUseSSRPluginConfig ? (0,external_utils_js_namespaceObject.createSSRMFConfig)(moduleFederationOptions) : undefined;
|
|
296
342
|
(_bundlerConfig_optimization1 = bundlerConfig.optimization) === null || _bundlerConfig_optimization1 === void 0 ? true : delete _bundlerConfig_optimization1.runtimeChunk;
|
|
297
343
|
const externals = bundlerConfig.externals;
|
|
298
344
|
if (Array.isArray(externals)) {
|
|
@@ -334,13 +380,12 @@ const pluginModuleFederation = (moduleFederationOptions, rsbuildOptions)=>({
|
|
|
334
380
|
}
|
|
335
381
|
}
|
|
336
382
|
}
|
|
337
|
-
if (!((_bundlerConfig_output = bundlerConfig.output) === null || _bundlerConfig_output === void 0 ? void 0 : _bundlerConfig_output.chunkLoadingGlobal) && !
|
|
383
|
+
if (!((_bundlerConfig_output = bundlerConfig.output) === null || _bundlerConfig_output === void 0 ? void 0 : _bundlerConfig_output.chunkLoadingGlobal) && !shouldUseSSRPluginConfig && !isActiveRspressSSGEnvironmentConfig && target !== 'node') {
|
|
338
384
|
bundlerConfig.output.chunkLoading = 'jsonp';
|
|
339
385
|
bundlerConfig.output.chunkLoadingGlobal = `chunk_${moduleFederationOptions.name} `;
|
|
340
386
|
}
|
|
341
|
-
if (
|
|
342
|
-
(0,ssr_js_namespaceObject.patchNodeConfig)(bundlerConfig, moduleFederationOptions);
|
|
343
|
-
(0,ssr_js_namespaceObject.patchNodeMFConfig)(moduleFederationOptions);
|
|
387
|
+
if (isNodeTargetEnvironmentConfig) {
|
|
388
|
+
(0,ssr_js_namespaceObject.patchNodeConfig)(bundlerConfig, ssrModuleFederationOptions ?? moduleFederationOptions);
|
|
344
389
|
}
|
|
345
390
|
// `uniqueName` is required for react refresh to work
|
|
346
391
|
if (!((_bundlerConfig_output1 = bundlerConfig.output) === null || _bundlerConfig_output1 === void 0 ? void 0 : _bundlerConfig_output1.uniqueName)) {
|
|
@@ -348,17 +393,18 @@ const pluginModuleFederation = (moduleFederationOptions, rsbuildOptions)=>({
|
|
|
348
393
|
}
|
|
349
394
|
// Set default publicPath to 'auto' if not explicitly configured
|
|
350
395
|
// This allows remote chunks to load from the same origin as the remote application's manifest
|
|
351
|
-
if (((_bundlerConfig_output2 = bundlerConfig.output) === null || _bundlerConfig_output2 === void 0 ? void 0 : _bundlerConfig_output2.publicPath) === undefined && !
|
|
396
|
+
if (((_bundlerConfig_output2 = bundlerConfig.output) === null || _bundlerConfig_output2 === void 0 ? void 0 : _bundlerConfig_output2.publicPath) === undefined && !shouldUseSSRPluginConfig && !isActiveRspressSSGEnvironmentConfig) {
|
|
352
397
|
bundlerConfig.output.publicPath = 'auto';
|
|
353
398
|
}
|
|
354
399
|
if (!bundlerConfig.plugins.find((p)=>p && p.name === rspack_namespaceObject.PLUGIN_NAME)) {
|
|
355
400
|
var _bundlerConfig_output3;
|
|
356
|
-
if (
|
|
357
|
-
|
|
401
|
+
if (shouldUseSSRPluginConfig) {
|
|
402
|
+
const ssrMFConfig = ssrModuleFederationOptions ?? (0,external_utils_js_namespaceObject.createSSRMFConfig)(moduleFederationOptions);
|
|
403
|
+
generateMergedStatsAndManifestOptions.options.nodePlugin = new rspack_namespaceObject.ModuleFederationPlugin(ssrMFConfig);
|
|
358
404
|
generateMergedStatsAndManifestOptions.options.nodeEnvironmentName = bundlerConfig.name || external_utils_js_namespaceObject.SSR_ENV_NAME;
|
|
359
405
|
bundlerConfig.plugins.push(generateMergedStatsAndManifestOptions.options.nodePlugin);
|
|
360
406
|
return;
|
|
361
|
-
} else if (
|
|
407
|
+
} else if (isActiveRspressSSGEnvironmentConfig) {
|
|
362
408
|
const mfConfig = {
|
|
363
409
|
...(0,external_utils_js_namespaceObject.createSSRMFConfig)(moduleFederationOptions),
|
|
364
410
|
// expose in mf-ssg env
|
package/dist/cli/index.mjs
CHANGED
|
@@ -5,7 +5,7 @@ import package_0 from "../../package.json";
|
|
|
5
5
|
import logger from "../logger.mjs";
|
|
6
6
|
import { SSR_DIR, SSR_ENV_NAME, addDataFetchExposes, autoDeleteSplitChunkCacheGroups, createSSRMFConfig, createSSRREnvConfig, isRegExp, patchSSRRspackConfig, setSSREnv, updateStatsAndManifest } from "../utils.mjs";
|
|
7
7
|
import { CALL_NAME_MAP, RSPRESS_BUNDLER_CONFIG_NAME, RSPRESS_SSG_MD_ENV_NAME, RSPRESS_SSR_DIR } from "../constant.mjs";
|
|
8
|
-
import {
|
|
8
|
+
import { patchNodeConfig, patchToolsTspack } from "../utils/ssr.mjs";
|
|
9
9
|
|
|
10
10
|
;// CONCATENATED MODULE: external "@module-federation/enhanced"
|
|
11
11
|
|
|
@@ -40,6 +40,23 @@ const LIB_FORMAT = [
|
|
|
40
40
|
'modern-module'
|
|
41
41
|
];
|
|
42
42
|
const DEFAULT_MF_ENVIRONMENT_NAME = 'mf';
|
|
43
|
+
const DEFAULT_WEB_ENVIRONMENT_NAME = 'web';
|
|
44
|
+
const DEFAULT_NODE_ENVIRONMENT_NAME = 'node';
|
|
45
|
+
const resolveDefaultEnvironmentName = ({ callerName, target })=>{
|
|
46
|
+
if (callerName === CALL_NAME_MAP.RSLIB) {
|
|
47
|
+
return DEFAULT_MF_ENVIRONMENT_NAME;
|
|
48
|
+
}
|
|
49
|
+
if (callerName === CALL_NAME_MAP.RSPRESS) {
|
|
50
|
+
if (target === 'node') {
|
|
51
|
+
return DEFAULT_NODE_ENVIRONMENT_NAME;
|
|
52
|
+
}
|
|
53
|
+
return DEFAULT_WEB_ENVIRONMENT_NAME;
|
|
54
|
+
}
|
|
55
|
+
if (target === 'node') {
|
|
56
|
+
return DEFAULT_NODE_ENVIRONMENT_NAME;
|
|
57
|
+
}
|
|
58
|
+
return DEFAULT_WEB_ENVIRONMENT_NAME;
|
|
59
|
+
};
|
|
43
60
|
function isStoryBook(rsbuildConfig) {
|
|
44
61
|
var _rsbuildConfig_plugins;
|
|
45
62
|
if ((_rsbuildConfig_plugins = rsbuildConfig.plugins) === null || _rsbuildConfig_plugins === void 0 ? void 0 : _rsbuildConfig_plugins.find((p)=>p && 'name' in p && p.name === 'module-federation-storybook-plugin')) {
|
|
@@ -66,7 +83,10 @@ const isRspressSSGConfig = (bundlerConfigName)=>{
|
|
|
66
83
|
const pluginModuleFederation = (moduleFederationOptions, rsbuildOptions)=>({
|
|
67
84
|
name: RSBUILD_PLUGIN_MODULE_FEDERATION_NAME,
|
|
68
85
|
setup: (api)=>{
|
|
69
|
-
|
|
86
|
+
if (!(moduleFederationOptions === null || moduleFederationOptions === void 0 ? void 0 : moduleFederationOptions.name)) {
|
|
87
|
+
throw new Error('The module federation option "name" is required in @module-federation/rsbuild-plugin.');
|
|
88
|
+
}
|
|
89
|
+
const { target = 'web', ssr = undefined, ssrDir = SSR_DIR, environment: configuredEnvironment } = rsbuildOptions || {};
|
|
70
90
|
if (ssr) {
|
|
71
91
|
throw new Error("The `ssr` option is deprecated. If you want to enable SSR, please use `target: 'dual'` instead.");
|
|
72
92
|
}
|
|
@@ -78,6 +98,10 @@ const pluginModuleFederation = (moduleFederationOptions, rsbuildOptions)=>({
|
|
|
78
98
|
const isRslib = callerName === CALL_NAME_MAP.RSLIB;
|
|
79
99
|
const isRspress = callerName === CALL_NAME_MAP.RSPRESS;
|
|
80
100
|
const isSSR = target === 'dual';
|
|
101
|
+
const environment = configuredEnvironment ?? resolveDefaultEnvironmentName({
|
|
102
|
+
callerName,
|
|
103
|
+
target
|
|
104
|
+
});
|
|
81
105
|
if (isSSR && !isStoryBook(originalRsbuildConfig)) {
|
|
82
106
|
var _rsbuildConfig_environments;
|
|
83
107
|
if (!isRslib && !isRspress) {
|
|
@@ -149,8 +173,14 @@ const pluginModuleFederation = (moduleFederationOptions, rsbuildOptions)=>({
|
|
|
149
173
|
});
|
|
150
174
|
}
|
|
151
175
|
} else if (target === 'node') {
|
|
152
|
-
|
|
153
|
-
|
|
176
|
+
var _config_environments2;
|
|
177
|
+
const nodeTargetEnv = (_config_environments2 = config.environments) === null || _config_environments2 === void 0 ? void 0 : _config_environments2[environment];
|
|
178
|
+
if (!nodeTargetEnv) {
|
|
179
|
+
const availableEnvironments = Object.keys(config.environments || {});
|
|
180
|
+
const availableEnvironmentsLabel = availableEnvironments.length > 0 ? availableEnvironments.join(', ') : '(none)';
|
|
181
|
+
throw new Error(`Can not find environment '${environment}' when using target: 'node'. Available environments: ${availableEnvironmentsLabel}.`);
|
|
182
|
+
}
|
|
183
|
+
patchToolsTspack(nodeTargetEnv, (config, { environment })=>{
|
|
154
184
|
config.target = 'async-node';
|
|
155
185
|
});
|
|
156
186
|
}
|
|
@@ -227,7 +257,22 @@ const pluginModuleFederation = (moduleFederationOptions, rsbuildOptions)=>({
|
|
|
227
257
|
throw new Error('Can not get bundlerConfigs!');
|
|
228
258
|
}
|
|
229
259
|
bundlerConfigs.forEach((bundlerConfig)=>{
|
|
230
|
-
|
|
260
|
+
const bundlerConfigName = bundlerConfig.name || '';
|
|
261
|
+
const isConfiguredEnvironmentConfig = bundlerConfigName === environment;
|
|
262
|
+
const isNodeTargetEnvironmentConfig = target === 'node' && bundlerConfigName === environment;
|
|
263
|
+
const isRspressSSGEnvironmentConfig = isRspressSSGConfig(bundlerConfig.name);
|
|
264
|
+
const isActiveRspressSSGEnvironmentConfig = isRspress && isRspressSSGEnvironmentConfig;
|
|
265
|
+
const shouldUseSSRPluginConfig = isSSRConfig(bundlerConfig.name) || isNodeTargetEnvironmentConfig;
|
|
266
|
+
if (target === 'node' && !isNodeTargetEnvironmentConfig && !isActiveRspressSSGEnvironmentConfig) {
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
// For non-node targets, scope each plugin instance to its configured
|
|
270
|
+
// environment plus explicit SSR/SSG environments. This prevents a
|
|
271
|
+
// browser-targeted instance from mutating SSR configs.
|
|
272
|
+
if (target !== 'node' && !isConfiguredEnvironmentConfig && !shouldUseSSRPluginConfig && !isActiveRspressSSGEnvironmentConfig) {
|
|
273
|
+
return;
|
|
274
|
+
}
|
|
275
|
+
if (!isMFFormat(bundlerConfig) && !isRspress && !isNodeTargetEnvironmentConfig) {
|
|
231
276
|
return;
|
|
232
277
|
} else if (isStoryBook(originalRsbuildConfig)) {
|
|
233
278
|
bundlerConfig.output.uniqueName = `${moduleFederationOptions.name} -storybook - host`;
|
|
@@ -235,7 +280,8 @@ const pluginModuleFederation = (moduleFederationOptions, rsbuildOptions)=>({
|
|
|
235
280
|
var _bundlerConfig_optimization, _bundlerConfig_optimization1, _bundlerConfig_output, _bundlerConfig_output1, _bundlerConfig_output2;
|
|
236
281
|
// mf
|
|
237
282
|
autoDeleteSplitChunkCacheGroups(moduleFederationOptions, bundlerConfig === null || bundlerConfig === void 0 ? void 0 : (_bundlerConfig_optimization = bundlerConfig.optimization) === null || _bundlerConfig_optimization === void 0 ? void 0 : _bundlerConfig_optimization.splitChunks);
|
|
238
|
-
addDataFetchExposes(moduleFederationOptions.exposes,
|
|
283
|
+
addDataFetchExposes(moduleFederationOptions.exposes, shouldUseSSRPluginConfig);
|
|
284
|
+
const ssrModuleFederationOptions = shouldUseSSRPluginConfig ? createSSRMFConfig(moduleFederationOptions) : undefined;
|
|
239
285
|
(_bundlerConfig_optimization1 = bundlerConfig.optimization) === null || _bundlerConfig_optimization1 === void 0 ? true : delete _bundlerConfig_optimization1.runtimeChunk;
|
|
240
286
|
const externals = bundlerConfig.externals;
|
|
241
287
|
if (Array.isArray(externals)) {
|
|
@@ -277,13 +323,12 @@ const pluginModuleFederation = (moduleFederationOptions, rsbuildOptions)=>({
|
|
|
277
323
|
}
|
|
278
324
|
}
|
|
279
325
|
}
|
|
280
|
-
if (!((_bundlerConfig_output = bundlerConfig.output) === null || _bundlerConfig_output === void 0 ? void 0 : _bundlerConfig_output.chunkLoadingGlobal) && !
|
|
326
|
+
if (!((_bundlerConfig_output = bundlerConfig.output) === null || _bundlerConfig_output === void 0 ? void 0 : _bundlerConfig_output.chunkLoadingGlobal) && !shouldUseSSRPluginConfig && !isActiveRspressSSGEnvironmentConfig && target !== 'node') {
|
|
281
327
|
bundlerConfig.output.chunkLoading = 'jsonp';
|
|
282
328
|
bundlerConfig.output.chunkLoadingGlobal = `chunk_${moduleFederationOptions.name} `;
|
|
283
329
|
}
|
|
284
|
-
if (
|
|
285
|
-
patchNodeConfig(bundlerConfig, moduleFederationOptions);
|
|
286
|
-
patchNodeMFConfig(moduleFederationOptions);
|
|
330
|
+
if (isNodeTargetEnvironmentConfig) {
|
|
331
|
+
patchNodeConfig(bundlerConfig, ssrModuleFederationOptions ?? moduleFederationOptions);
|
|
287
332
|
}
|
|
288
333
|
// `uniqueName` is required for react refresh to work
|
|
289
334
|
if (!((_bundlerConfig_output1 = bundlerConfig.output) === null || _bundlerConfig_output1 === void 0 ? void 0 : _bundlerConfig_output1.uniqueName)) {
|
|
@@ -291,17 +336,18 @@ const pluginModuleFederation = (moduleFederationOptions, rsbuildOptions)=>({
|
|
|
291
336
|
}
|
|
292
337
|
// Set default publicPath to 'auto' if not explicitly configured
|
|
293
338
|
// This allows remote chunks to load from the same origin as the remote application's manifest
|
|
294
|
-
if (((_bundlerConfig_output2 = bundlerConfig.output) === null || _bundlerConfig_output2 === void 0 ? void 0 : _bundlerConfig_output2.publicPath) === undefined && !
|
|
339
|
+
if (((_bundlerConfig_output2 = bundlerConfig.output) === null || _bundlerConfig_output2 === void 0 ? void 0 : _bundlerConfig_output2.publicPath) === undefined && !shouldUseSSRPluginConfig && !isActiveRspressSSGEnvironmentConfig) {
|
|
295
340
|
bundlerConfig.output.publicPath = 'auto';
|
|
296
341
|
}
|
|
297
342
|
if (!bundlerConfig.plugins.find((p)=>p && p.name === PLUGIN_NAME)) {
|
|
298
343
|
var _bundlerConfig_output3;
|
|
299
|
-
if (
|
|
300
|
-
|
|
344
|
+
if (shouldUseSSRPluginConfig) {
|
|
345
|
+
const ssrMFConfig = ssrModuleFederationOptions ?? createSSRMFConfig(moduleFederationOptions);
|
|
346
|
+
generateMergedStatsAndManifestOptions.options.nodePlugin = new ModuleFederationPlugin(ssrMFConfig);
|
|
301
347
|
generateMergedStatsAndManifestOptions.options.nodeEnvironmentName = bundlerConfig.name || SSR_ENV_NAME;
|
|
302
348
|
bundlerConfig.plugins.push(generateMergedStatsAndManifestOptions.options.nodePlugin);
|
|
303
349
|
return;
|
|
304
|
-
} else if (
|
|
350
|
+
} else if (isActiveRspressSSGEnvironmentConfig) {
|
|
305
351
|
const mfConfig = {
|
|
306
352
|
...createSSRMFConfig(moduleFederationOptions),
|
|
307
353
|
// expose in mf-ssg env
|
package/dist/utils/ssr.js
CHANGED
|
@@ -81,6 +81,20 @@ const external_constant_js_namespaceObject = require("../constant.js");
|
|
|
81
81
|
|
|
82
82
|
const ssr_require = (0,external_node_module_namespaceObject.createRequire)(__rslib_import_meta_url__);
|
|
83
83
|
const resolve = ssr_require.resolve;
|
|
84
|
+
function resolveOrRequest(request) {
|
|
85
|
+
try {
|
|
86
|
+
return resolve(request);
|
|
87
|
+
} catch {
|
|
88
|
+
return request;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function safeRequire(request) {
|
|
92
|
+
try {
|
|
93
|
+
return ssr_require(request);
|
|
94
|
+
} catch {
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
84
98
|
const SSR_DIR = 'ssr';
|
|
85
99
|
const SSR_ENV_NAME = 'mf-ssr';
|
|
86
100
|
const ENV_NAME = 'mf';
|
|
@@ -93,16 +107,27 @@ const isDev = ()=>{
|
|
|
93
107
|
function patchNodeConfig(config, mfConfig) {
|
|
94
108
|
var _config_output;
|
|
95
109
|
config.output ||= {};
|
|
110
|
+
if (config.output.publicPath === 'auto') {
|
|
111
|
+
config.output.publicPath = '';
|
|
112
|
+
}
|
|
96
113
|
config.target = 'async-node';
|
|
97
|
-
//
|
|
98
|
-
|
|
114
|
+
// Force node federation output to CJS + async chunk loading.
|
|
115
|
+
// This prevents browser jsonp runtime handlers from leaking into SSR remotes.
|
|
116
|
+
config.output.module = false;
|
|
117
|
+
config.output.chunkFormat = 'commonjs';
|
|
118
|
+
config.output.chunkLoading = 'async-node';
|
|
119
|
+
delete config.output.chunkLoadingGlobal;
|
|
120
|
+
const UniverseEntryChunkTrackerPluginModule = safeRequire('@module-federation/node/universe-entry-chunk-tracker-plugin');
|
|
121
|
+
const UniverseEntryChunkTrackerPlugin = UniverseEntryChunkTrackerPluginModule === null || UniverseEntryChunkTrackerPluginModule === void 0 ? void 0 : UniverseEntryChunkTrackerPluginModule.default;
|
|
99
122
|
config.plugins ||= [];
|
|
100
|
-
isDev() &&
|
|
123
|
+
if (isDev() && UniverseEntryChunkTrackerPlugin) {
|
|
124
|
+
config.plugins.push(new UniverseEntryChunkTrackerPlugin());
|
|
125
|
+
}
|
|
101
126
|
const uniqueName = mfConfig.name || ((_config_output = config.output) === null || _config_output === void 0 ? void 0 : _config_output.uniqueName);
|
|
102
127
|
const chunkFileName = config.output.chunkFilename;
|
|
103
128
|
if (typeof chunkFileName === 'string' && uniqueName && !chunkFileName.includes(uniqueName)) {
|
|
104
|
-
const
|
|
105
|
-
config.output.chunkFilename = chunkFileName.
|
|
129
|
+
const encodedName = (0,sdk_namespaceObject.encodeName)(uniqueName);
|
|
130
|
+
config.output.chunkFilename = chunkFileName.endsWith('.js') ? chunkFileName.replace(/\.js$/, `${encodedName}.js`) : `${chunkFileName}${encodedName}`;
|
|
106
131
|
}
|
|
107
132
|
}
|
|
108
133
|
function patchSSRRspackConfig(config, mfConfig, ssrDir, callerName, resetEntry = true, modifyPublicPath = true) {
|
|
@@ -113,11 +138,10 @@ function patchSSRRspackConfig(config, mfConfig, ssrDir, callerName, resetEntry =
|
|
|
113
138
|
throw new Error('publicPath must be string!');
|
|
114
139
|
}
|
|
115
140
|
const publicPath = config.output.publicPath;
|
|
116
|
-
if (publicPath
|
|
117
|
-
|
|
141
|
+
if (publicPath !== 'auto') {
|
|
142
|
+
const publicPathWithSSRDir = `${publicPath}${ssrDir}/`;
|
|
143
|
+
config.output.publicPath = publicPathWithSSRDir;
|
|
118
144
|
}
|
|
119
|
-
const publicPathWithSSRDir = `${publicPath}${ssrDir}/`;
|
|
120
|
-
config.output.publicPath = publicPathWithSSRDir;
|
|
121
145
|
}
|
|
122
146
|
if (callerName === external_constant_js_namespaceObject.CALL_NAME_MAP.RSPRESS && resetEntry) {
|
|
123
147
|
// set virtue entry, only need mf entry
|
|
@@ -196,10 +220,9 @@ function patchNodeMFConfig(mfConfig) {
|
|
|
196
220
|
mfConfig.runtimePlugins = [
|
|
197
221
|
...mfConfig.runtimePlugins || []
|
|
198
222
|
];
|
|
199
|
-
mfConfig.runtimePlugins.push(
|
|
223
|
+
mfConfig.runtimePlugins.push(resolveOrRequest('@module-federation/node/runtimePlugin'));
|
|
200
224
|
if (isDev()) {
|
|
201
|
-
mfConfig.runtimePlugins.push(
|
|
202
|
-
resolve('@module-federation/node/record-dynamic-remote-entry-hash-plugin'));
|
|
225
|
+
mfConfig.runtimePlugins.push(resolveOrRequest('@module-federation/node/record-dynamic-remote-entry-hash-plugin'));
|
|
203
226
|
}
|
|
204
227
|
}
|
|
205
228
|
function createSSRMFConfig(mfConfig) {
|
package/dist/utils/ssr.mjs
CHANGED
|
@@ -18,6 +18,20 @@ import { CALL_NAME_MAP } from "../constant.mjs";
|
|
|
18
18
|
|
|
19
19
|
const ssr_require = createRequire(import.meta.url);
|
|
20
20
|
const resolve = ssr_require.resolve;
|
|
21
|
+
function resolveOrRequest(request) {
|
|
22
|
+
try {
|
|
23
|
+
return resolve(request);
|
|
24
|
+
} catch {
|
|
25
|
+
return request;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function safeRequire(request) {
|
|
29
|
+
try {
|
|
30
|
+
return ssr_require(request);
|
|
31
|
+
} catch {
|
|
32
|
+
return undefined;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
21
35
|
const SSR_DIR = 'ssr';
|
|
22
36
|
const SSR_ENV_NAME = 'mf-ssr';
|
|
23
37
|
const ENV_NAME = 'mf';
|
|
@@ -30,16 +44,27 @@ const isDev = ()=>{
|
|
|
30
44
|
function patchNodeConfig(config, mfConfig) {
|
|
31
45
|
var _config_output;
|
|
32
46
|
config.output ||= {};
|
|
47
|
+
if (config.output.publicPath === 'auto') {
|
|
48
|
+
config.output.publicPath = '';
|
|
49
|
+
}
|
|
33
50
|
config.target = 'async-node';
|
|
34
|
-
//
|
|
35
|
-
|
|
51
|
+
// Force node federation output to CJS + async chunk loading.
|
|
52
|
+
// This prevents browser jsonp runtime handlers from leaking into SSR remotes.
|
|
53
|
+
config.output.module = false;
|
|
54
|
+
config.output.chunkFormat = 'commonjs';
|
|
55
|
+
config.output.chunkLoading = 'async-node';
|
|
56
|
+
delete config.output.chunkLoadingGlobal;
|
|
57
|
+
const UniverseEntryChunkTrackerPluginModule = safeRequire('@module-federation/node/universe-entry-chunk-tracker-plugin');
|
|
58
|
+
const UniverseEntryChunkTrackerPlugin = UniverseEntryChunkTrackerPluginModule === null || UniverseEntryChunkTrackerPluginModule === void 0 ? void 0 : UniverseEntryChunkTrackerPluginModule.default;
|
|
36
59
|
config.plugins ||= [];
|
|
37
|
-
isDev() &&
|
|
60
|
+
if (isDev() && UniverseEntryChunkTrackerPlugin) {
|
|
61
|
+
config.plugins.push(new UniverseEntryChunkTrackerPlugin());
|
|
62
|
+
}
|
|
38
63
|
const uniqueName = mfConfig.name || ((_config_output = config.output) === null || _config_output === void 0 ? void 0 : _config_output.uniqueName);
|
|
39
64
|
const chunkFileName = config.output.chunkFilename;
|
|
40
65
|
if (typeof chunkFileName === 'string' && uniqueName && !chunkFileName.includes(uniqueName)) {
|
|
41
|
-
const
|
|
42
|
-
config.output.chunkFilename = chunkFileName.
|
|
66
|
+
const encodedName = encodeName(uniqueName);
|
|
67
|
+
config.output.chunkFilename = chunkFileName.endsWith('.js') ? chunkFileName.replace(/\.js$/, `${encodedName}.js`) : `${chunkFileName}${encodedName}`;
|
|
43
68
|
}
|
|
44
69
|
}
|
|
45
70
|
function patchSSRRspackConfig(config, mfConfig, ssrDir, callerName, resetEntry = true, modifyPublicPath = true) {
|
|
@@ -50,11 +75,10 @@ function patchSSRRspackConfig(config, mfConfig, ssrDir, callerName, resetEntry =
|
|
|
50
75
|
throw new Error('publicPath must be string!');
|
|
51
76
|
}
|
|
52
77
|
const publicPath = config.output.publicPath;
|
|
53
|
-
if (publicPath
|
|
54
|
-
|
|
78
|
+
if (publicPath !== 'auto') {
|
|
79
|
+
const publicPathWithSSRDir = `${publicPath}${ssrDir}/`;
|
|
80
|
+
config.output.publicPath = publicPathWithSSRDir;
|
|
55
81
|
}
|
|
56
|
-
const publicPathWithSSRDir = `${publicPath}${ssrDir}/`;
|
|
57
|
-
config.output.publicPath = publicPathWithSSRDir;
|
|
58
82
|
}
|
|
59
83
|
if (callerName === CALL_NAME_MAP.RSPRESS && resetEntry) {
|
|
60
84
|
// set virtue entry, only need mf entry
|
|
@@ -133,10 +157,9 @@ function patchNodeMFConfig(mfConfig) {
|
|
|
133
157
|
mfConfig.runtimePlugins = [
|
|
134
158
|
...mfConfig.runtimePlugins || []
|
|
135
159
|
];
|
|
136
|
-
mfConfig.runtimePlugins.push(
|
|
160
|
+
mfConfig.runtimePlugins.push(resolveOrRequest('@module-federation/node/runtimePlugin'));
|
|
137
161
|
if (isDev()) {
|
|
138
|
-
mfConfig.runtimePlugins.push(
|
|
139
|
-
resolve('@module-federation/node/record-dynamic-remote-entry-hash-plugin'));
|
|
162
|
+
mfConfig.runtimePlugins.push(resolveOrRequest('@module-federation/node/record-dynamic-remote-entry-hash-plugin'));
|
|
140
163
|
}
|
|
141
164
|
}
|
|
142
165
|
function createSSRMFConfig(mfConfig) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@module-federation/rsbuild-plugin",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Module Federation plugin for Rsbuild",
|
|
5
5
|
"homepage": "https://module-federation.io",
|
|
6
6
|
"bugs": {
|
|
@@ -50,16 +50,16 @@
|
|
|
50
50
|
],
|
|
51
51
|
"dependencies": {
|
|
52
52
|
"fs-extra": "11.3.0",
|
|
53
|
-
"@module-federation/sdk": "2.0
|
|
54
|
-
"@module-federation/enhanced": "2.0
|
|
55
|
-
"@module-federation/node": "2.7.
|
|
53
|
+
"@module-federation/sdk": "2.1.0",
|
|
54
|
+
"@module-federation/enhanced": "2.1.0",
|
|
55
|
+
"@module-federation/node": "2.7.33"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@rslib/core": "^0.12.4",
|
|
59
59
|
"@rsbuild/core": "2.0.0-beta.2"
|
|
60
60
|
},
|
|
61
61
|
"peerDependencies": {
|
|
62
|
-
"@rsbuild/core": "2.0.0-
|
|
62
|
+
"@rsbuild/core": "^1.3.21 || ^2.0.0-0"
|
|
63
63
|
},
|
|
64
64
|
"peerDependenciesMeta": {
|
|
65
65
|
"@rsbuild/core": {
|