From b1a58c81c0e9bfdb96bf9fb7c0cfe8cc096c6e33 Mon Sep 17 00:00:00 2001 From: 2heal1 Date: Tue, 12 Nov 2024 17:08:06 +0800 Subject: [PATCH] chore(rsbuild-plugin): split setUp function to help extend --- .changeset/angry-spoons-wink.md | 5 + packages/rsbuild-plugin/src/cli/index.ts | 245 ++++++++++++----------- 2 files changed, 131 insertions(+), 119 deletions(-) create mode 100644 .changeset/angry-spoons-wink.md diff --git a/.changeset/angry-spoons-wink.md b/.changeset/angry-spoons-wink.md new file mode 100644 index 00000000000..c2095973b8d --- /dev/null +++ b/.changeset/angry-spoons-wink.md @@ -0,0 +1,5 @@ +--- +'@module-federation/rsbuild-plugin': patch +--- + +chore(rsbuild-plugin): split setUp function to help extend diff --git a/packages/rsbuild-plugin/src/cli/index.ts b/packages/rsbuild-plugin/src/cli/index.ts index 8c4ec2393bd..38bbe6e8350 100644 --- a/packages/rsbuild-plugin/src/cli/index.ts +++ b/packages/rsbuild-plugin/src/cli/index.ts @@ -16,140 +16,147 @@ type ModuleFederationOptions = moduleFederationPlugin.ModuleFederationPluginOptions; const PLUGIN_MODULE_FEDERATION_NAME = 'rsbuild:module-federation-enhanced'; -export const pluginModuleFederation = ( - moduleFederationOptions: ModuleFederationOptions, -): RsbuildPlugin => ({ - name: PLUGIN_MODULE_FEDERATION_NAME, - setup: (api) => { - const sharedOptions: [string, sharePlugin.SharedConfig][] = parseOptions( - moduleFederationOptions.shared || [], - (item, key) => { - if (typeof item !== 'string') - throw new Error('Unexpected array in shared'); - const config: sharePlugin.SharedConfig = - item === key || !isRequiredVersion(item) - ? { - import: item, - } - : { - import: key, - requiredVersion: item, - }; - return config; - }, - (item) => item, - ); - // shared[0] is the shared name - const shared = sharedOptions.map((shared) => - shared[0].endsWith('/') ? shared[0].slice(0, -1) : shared[0], - ); - - api.modifyRsbuildConfig((config) => { - // Change some default configs for remote modules - if (moduleFederationOptions.exposes) { - config.dev ||= {}; - - // For remote modules, Rsbuild should send the ws request to the provider's dev server. - // This allows the provider to do HMR when the provider module is loaded in the consumer's page. - if (config.server?.port && !config.dev.client?.port) { - config.dev.client ||= {}; - config.dev.client.port = config.server.port; - } - // Change the default assetPrefix to `true` for remote modules. - // This ensures that the remote module's assets can be requested by consumer apps with the correct URL. - const originalConfig = api.getRsbuildConfig('original'); - if ( - originalConfig.dev?.assetPrefix === undefined && - config.dev.assetPrefix === config.server?.base - ) { - config.dev.assetPrefix = true; - } +export const setupRsbuildConfig: ( + moduleFederationOptions: ModuleFederationOptions, +) => RsbuildPlugin['setup'] = (moduleFederationOptions) => (api) => { + const sharedOptions: [string, sharePlugin.SharedConfig][] = parseOptions( + moduleFederationOptions.shared || [], + (item, key) => { + if (typeof item !== 'string') + throw new Error('Unexpected array in shared'); + const config: sharePlugin.SharedConfig = + item === key || !isRequiredVersion(item) + ? { + import: item, + } + : { + import: key, + requiredVersion: item, + }; + return config; + }, + (item) => item, + ); + // shared[0] is the shared name + const shared = sharedOptions.map((shared) => + shared[0].endsWith('/') ? shared[0].slice(0, -1) : shared[0], + ); + + api.modifyRsbuildConfig((config) => { + // Change some default configs for remote modules + if (moduleFederationOptions.exposes) { + config.dev ||= {}; + + // For remote modules, Rsbuild should send the ws request to the provider's dev server. + // This allows the provider to do HMR when the provider module is loaded in the consumer's page. + if (config.server?.port && !config.dev.client?.port) { + config.dev.client ||= {}; + config.dev.client.port = config.server.port; } - }); - api.modifyEnvironmentConfig((config, { mergeEnvironmentConfig }) => { - /** - * Currently, splitChunks will take precedence over module federation shared modules. - * So we need to disable the default split chunks rules to make shared modules to work properly. - * @see https://github.com/module-federation/module-federation-examples/issues/3161 - */ - if (config.performance?.chunkSplit?.strategy === 'split-by-experience') { - config.performance.chunkSplit = { - ...config.performance.chunkSplit, - strategy: 'custom', - }; + // Change the default assetPrefix to `true` for remote modules. + // This ensures that the remote module's assets can be requested by consumer apps with the correct URL. + const originalConfig = api.getRsbuildConfig('original'); + if ( + originalConfig.dev?.assetPrefix === undefined && + config.dev.assetPrefix === config.server?.base + ) { + config.dev.assetPrefix = true; } + } + }); + + api.modifyEnvironmentConfig((config, { mergeEnvironmentConfig }) => { + /** + * Currently, splitChunks will take precedence over module federation shared modules. + * So we need to disable the default split chunks rules to make shared modules to work properly. + * @see https://github.com/module-federation/module-federation-examples/issues/3161 + */ + if (config.performance?.chunkSplit?.strategy === 'split-by-experience') { + config.performance.chunkSplit = { + ...config.performance.chunkSplit, + strategy: 'custom', + }; + } + + // Module Federation runtime uses ES6+ syntax, + // adding to include and let SWC transform it + config.source.include = [ + ...(config.source.include || []), + /@module-federation[\\/]sdk/, + /@module-federation[\\/]runtime/, + ]; + + // filter external with shared config, + const externals = config.output.externals; + if (Array.isArray(externals)) { + const sharedModules = new Set(); + config.output.externals = externals.filter((ext) => { + let sharedModule; + if (isRegExp(ext)) { + const match = shared.some((dep) => { + if ( + (ext as RegExp).test(dep) || + (ext as RegExp).test(pkgJson.name) + ) { + sharedModule = dep; + return true; + } + return false; + }); - // Module Federation runtime uses ES6+ syntax, - // adding to include and let SWC transform it - config.source.include = [ - ...(config.source.include || []), - /@module-federation[\\/]sdk/, - /@module-federation[\\/]runtime/, - ]; - - // filter external with shared config, - const externals = config.output.externals; - if (Array.isArray(externals)) { - const sharedModules = new Set(); - config.output.externals = externals.filter((ext) => { - let sharedModule; - if (isRegExp(ext)) { - const match = shared.some((dep) => { - if ( - (ext as RegExp).test(dep) || - (ext as RegExp).test(pkgJson.name) - ) { - sharedModule = dep; - return true; - } - return false; - }); - - match && sharedModule && sharedModules.add(sharedModule); - return !match; - } + match && sharedModule && sharedModules.add(sharedModule); + return !match; + } - if (typeof ext === 'string') { - if (ext === pkgJson.name) { - return false; - } + if (typeof ext === 'string') { + if (ext === pkgJson.name) { + return false; + } - const match = shared.some((dep) => { - if (dep === ext) { - sharedModule = dep; - } - return dep === ext; - }); - if (match) { - sharedModule && sharedModules.add(sharedModule); - return false; + const match = shared.some((dep) => { + if (dep === ext) { + sharedModule = dep; } - return true; + return dep === ext; + }); + if (match) { + sharedModule && sharedModules.add(sharedModule); + return false; } return true; - }); - if (sharedModules.size > 0) { - for (const sharedModule of sharedModules) { - logger.log( - `${sharedModule} is removed from externals because it is a shared module.`, - ); - } + } + return true; + }); + if (sharedModules.size > 0) { + for (const sharedModule of sharedModules) { + logger.log( + `${sharedModule} is removed from externals because it is a shared module.`, + ); } } + } - const mfConfig: EnvironmentConfig = { - tools: { - rspack: { - output: { - chunkLoading: 'jsonp', - }, + const mfConfig: EnvironmentConfig = { + tools: { + rspack: { + output: { + chunkLoading: 'jsonp', }, }, - }; - return mergeEnvironmentConfig(config, mfConfig); - }); + }, + }; + return mergeEnvironmentConfig(config, mfConfig); + }); +}; + +export const pluginModuleFederation = ( + moduleFederationOptions: ModuleFederationOptions, +): RsbuildPlugin => ({ + name: PLUGIN_MODULE_FEDERATION_NAME, + setup: (api) => { + setupRsbuildConfig(moduleFederationOptions)(api); api.modifyBundlerChain(async (chain) => { chain