diff --git a/e2e/cases/plugin-react/split-chunk/index.test.ts b/e2e/cases/plugin-react/split-chunk/index.test.ts index e4e232d2a5..157856d2a4 100644 --- a/e2e/cases/plugin-react/split-chunk/index.test.ts +++ b/e2e/cases/plugin-react/split-chunk/index.test.ts @@ -34,6 +34,25 @@ test('should not split react chunks when strategy is `all-in-one`', async ({ expect(filesNames.find((file) => file.includes('lib-router'))).toBeFalsy(); }); +test('should not split react chunks when splitChunks is disabled', async ({ + build, +}) => { + const rsbuild = await build({ + config: { + plugins: [ + pluginReact({ + splitChunks: false, + }), + ], + }, + }); + + const files = rsbuild.getDistFiles(); + const filesNames = Object.keys(files); + expect(filesNames.find((file) => file.includes('lib-react'))).toBeFalsy(); + expect(filesNames.find((file) => file.includes('lib-router'))).toBeFalsy(); +}); + test('should not override user defined cache groups', async ({ build }) => { const rsbuild = await build({ config: { diff --git a/packages/plugin-react/src/index.ts b/packages/plugin-react/src/index.ts index 3501b28078..64839c3e00 100644 --- a/packages/plugin-react/src/index.ts +++ b/packages/plugin-react/src/index.ts @@ -25,9 +25,11 @@ export type PluginReactOptions = { */ swcReactOptions?: Rspack.SwcLoaderTransformConfig['react']; /** - * Configuration for chunk splitting of React-related dependencies. + * Configuration for chunk splitting of React-related dependencies when `chunkSplit.strategy` + * is set to `split-by-experience`. + * @default true */ - splitChunks?: SplitReactChunkOptions; + splitChunks?: boolean | SplitReactChunkOptions; /** * When set to `true`, enables the React Profiler for performance analysis in production builds. * @default false @@ -59,10 +61,11 @@ export const pluginReact = ( name: PLUGIN_REACT_NAME, setup(api) { - const defaultOptions: PluginReactOptions = { + const defaultOptions = { fastRefresh: true, + splitChunks: true, enableProfiler: false, - }; + } satisfies PluginReactOptions; const finalOptions = { ...defaultOptions, ...options, @@ -76,6 +79,6 @@ export const pluginReact = ( } } - applySplitChunksRule(api, finalOptions?.splitChunks); + applySplitChunksRule(api, finalOptions.splitChunks); }, }); diff --git a/packages/plugin-react/src/splitChunks.ts b/packages/plugin-react/src/splitChunks.ts index dcc68ba660..5fbb5796b8 100644 --- a/packages/plugin-react/src/splitChunks.ts +++ b/packages/plugin-react/src/splitChunks.ts @@ -1,27 +1,25 @@ import type { RsbuildPluginAPI, Rspack } from '@rsbuild/core'; import type { SplitReactChunkOptions } from './index.js'; -const isPlainObject = (obj: unknown): obj is Record => - obj !== null && - typeof obj === 'object' && - Object.prototype.toString.call(obj) === '[object Object]'; - export const applySplitChunksRule = ( api: RsbuildPluginAPI, - options: SplitReactChunkOptions = { - react: true, - router: true, - }, + options: SplitReactChunkOptions | boolean, ): void => { api.modifyBundlerChain((chain, { environment, isProd }) => { const { config } = environment; - if (config.performance.chunkSplit.strategy !== 'split-by-experience') { + if ( + config.performance.chunkSplit.strategy !== 'split-by-experience' || + options === false + ) { return; } + const normalizedOptions = + options === true ? { react: true, router: true } : options; + const currentConfig = chain.optimization.splitChunks.values() as Rspack.Optimization['splitChunks']; - if (!isPlainObject(currentConfig)) { + if (typeof currentConfig !== 'object') { return; } @@ -30,7 +28,7 @@ export const applySplitChunksRule = ( Rspack.OptimizationSplitChunksCacheGroup > = {}; - if (options.react) { + if (normalizedOptions.react) { extraGroups.react = { name: 'lib-react', test: isProd @@ -40,7 +38,7 @@ export const applySplitChunksRule = ( }; } - if (options.router) { + if (normalizedOptions.router) { extraGroups.router = { name: 'lib-router', test: /node_modules[\\/](?:react-router|react-router-dom|history|@remix-run[\\/]router)[\\/]/, diff --git a/website/docs/en/plugins/list/plugin-react.mdx b/website/docs/en/plugins/list/plugin-react.mdx index a9c16dc145..da423fceac 100644 --- a/website/docs/en/plugins/list/plugin-react.mdx +++ b/website/docs/en/plugins/list/plugin-react.mdx @@ -158,27 +158,28 @@ This option is used to control this behavior and determine whether the `react` a - **Type:** ```ts -type SplitReactChunkOptions = { - react?: boolean; - router?: boolean; -}; +type SplitChunks = + | boolean + | { + react?: boolean; + router?: boolean; + }; ``` -- **Default:** +- **Default:** `true` (equivalent to `{ react: true, router: true }`) + +For example, to disable all chunk splitting: ```ts -const defaultOptions = { - react: true, - router: true, -}; +pluginReact({ splitChunks: false }); ``` -- **Example:** +Or to disable only the `router` chunk splitting: ```ts pluginReact({ splitChunks: { - react: false, + react: true, router: false, }, }); diff --git a/website/docs/zh/plugins/list/plugin-react.mdx b/website/docs/zh/plugins/list/plugin-react.mdx index 6a0889611f..59b772217a 100644 --- a/website/docs/zh/plugins/list/plugin-react.mdx +++ b/website/docs/zh/plugins/list/plugin-react.mdx @@ -158,27 +158,28 @@ pluginReact({ - **类型:** ```ts -type SplitReactChunkOptions = { - react?: boolean; - router?: boolean; -}; +type SplitChunks = + | boolean + | { + react?: boolean; + router?: boolean; + }; ``` -- **默认值:** +- **默认值:** `true`(等价于 `{ react: true, router: true }`) + +例如,禁用所有 chunks 拆分: ```ts -const defaultOptions = { - react: true, - router: true, -}; +pluginReact({ splitChunks: false }); ``` -- **示例:** +或是仅禁用 `router` chunk 拆分: ```ts pluginReact({ splitChunks: { - react: false, + react: true, router: false, }, });