feat: introduce new splitChunks config#7073
Conversation
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Summary of ChangesHello @chenjiahan, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request significantly revamps the chunk splitting configuration in Rsbuild 2.0 by introducing a new top-level Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces a new top-level splitChunks option, aligning Rsbuild more closely with Rspack's optimization.splitChunks configuration. It deprecates the legacy performance.chunkSplit option and provides backward compatibility. The changes include updating default configurations, introducing new types, and refactoring the split chunks logic into a more modular, preset-based approach. Test snapshots and plugin integrations have also been updated to reflect these changes.
| if (chunkSplit) { | ||
| logger.warn( | ||
| '[rsbuild:config] Both `performance.chunkSplit` and `splitChunks` are set. The `performance.chunkSplit` option is deprecated and will not work. Use `splitChunks` instead.', | ||
| ); |
There was a problem hiding this comment.
The warning message here states that performance.chunkSplit "will not work" if both performance.chunkSplit and splitChunks are set. However, the preceding if block (lines 293-305) explicitly handles the case where chunkSplit is present and splitChunks is an empty object, by calling makeLegacySplitChunksOptions which uses chunkSplit. This means performance.chunkSplit will work in that specific scenario.
To avoid confusion, consider clarifying the warning message to accurately reflect when performance.chunkSplit is ignored versus when it's used for backward compatibility. For example, you could state that performance.chunkSplit is ignored if splitChunks is explicitly configured with non-empty options, but will be used if splitChunks is an empty object (default behavior).
Alternatively, if the intention is for performance.chunkSplit to truly be ignored when splitChunks is present (even if empty), then the logic in lines 293-305 should be re-evaluated.
There was a problem hiding this comment.
Pull request overview
This PR introduces a new top-level splitChunks configuration option in Rsbuild 2.0 to replace the deprecated performance.chunkSplit option. The goal is to align more closely with Rspack's native optimization.splitChunks API while maintaining backward compatibility and providing convenient presets.
Changes:
- Added new
splitChunksconfiguration option with support forpresetproperty ('default', 'per-package', 'single-vendor') - Deprecated
performance.chunkSplitwith backward compatibility support - Updated plugin-vue and plugin-react to work with both old and new configurations
- Updated tests and snapshots to reflect the new configuration structure
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/core/src/types/config.ts | Added type definitions for SplitChunksConfig, SplitChunksPreset, and NormalizedSplitChunksConfig; deprecated chunkSplit in PerformanceConfig |
| packages/core/src/defaultConfig.ts | Removed default chunkSplit configuration; added splitChunks: {} as default |
| packages/core/src/plugins/splitChunks.ts | Refactored to support new splitChunks configuration with presets; added backward compatibility logic for legacy chunkSplit option |
| packages/core/src/index.ts | Exported new types: NormalizedSplitChunksConfig, SplitChunksConfig, SplitChunksPreset |
| packages/plugin-vue/src/splitChunks.ts | Updated isDefaultPreset helper to check new splitChunks config with fallback to legacy chunkSplit |
| packages/plugin-react/src/splitChunks.ts | Updated isDefaultPreset helper to check new splitChunks config with fallback to legacy chunkSplit |
| packages/core/tests/splitChunks.test.ts | Rewrote tests to use new splitChunks configuration instead of legacy chunkSplit |
| packages/core/tests/snapshots/splitChunks.test.ts.snap | Updated snapshots for new test structure |
| packages/core/tests/snapshots/environments.test.ts.snap | Updated snapshots showing splitChunks: {} in normalized config and removal of chunkSplit from performance config |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| describe('plugin-split-chunks', () => { | ||
| it('should set split-by-experience config', async () => { | ||
| const rsbuild = await createStubRsbuild({ | ||
| plugins: [pluginSplitChunks()], | ||
| it('should set `default` preset by default', async () => { | ||
| const rsbuild = await createRsbuild({ | ||
| config: { | ||
| performance: { | ||
| chunkSplit: { | ||
| strategy: 'split-by-experience', | ||
| }, | ||
| }, | ||
| output: { | ||
| polyfill: 'entry', | ||
| }, | ||
| }, | ||
| }); | ||
|
|
||
| const config = await rsbuild.unwrapConfig(); | ||
| expect(config).toMatchSnapshot(); | ||
| const config = await rsbuild.initConfigs(); | ||
| expect(config[0].optimization?.splitChunks).toMatchSnapshot(); | ||
| }); | ||
|
|
||
| it('should set split-by-experience config correctly when polyfill is off', async () => { | ||
| const rsbuild = await createStubRsbuild({ | ||
| plugins: [pluginSplitChunks()], | ||
| it('should set `per-package` preset', async () => { | ||
| const rsbuild = await createRsbuild({ | ||
| config: { | ||
| performance: { | ||
| chunkSplit: { | ||
| strategy: 'split-by-experience', | ||
| }, | ||
| }, | ||
| output: { | ||
| polyfill: 'off', | ||
| }, | ||
| }, | ||
| }); | ||
|
|
||
| const config = await rsbuild.unwrapConfig(); | ||
| expect(config).toMatchSnapshot(); | ||
| }); | ||
|
|
||
| it('should set split-by-module config', async () => { | ||
| const rsbuild = await createStubRsbuild({ | ||
| plugins: [pluginSplitChunks()], | ||
| config: { | ||
| performance: { | ||
| chunkSplit: { | ||
| strategy: 'split-by-module', | ||
| }, | ||
| }, | ||
| output: { | ||
| polyfill: 'entry', | ||
| }, | ||
| }, | ||
| }); | ||
|
|
||
| const config = await rsbuild.unwrapConfig(); | ||
| expect(config).toMatchSnapshot(); | ||
| }); | ||
|
|
||
| it('should set single-vendor config', async () => { | ||
| const rsbuild = await createStubRsbuild({ | ||
| plugins: [pluginSplitChunks()], | ||
| config: { | ||
| performance: { | ||
| chunkSplit: { | ||
| strategy: 'single-vendor', | ||
| }, | ||
| }, | ||
| output: { | ||
| polyfill: 'entry', | ||
| splitChunks: { | ||
| preset: 'per-package', | ||
| }, | ||
| }, | ||
| }); | ||
|
|
||
| const config = await rsbuild.unwrapConfig(); | ||
| expect(config).toMatchSnapshot(); | ||
| const config = await rsbuild.initConfigs(); | ||
| expect(config[0].optimization?.splitChunks).toMatchSnapshot(); | ||
| }); | ||
|
|
||
| it('should set single-size config', async () => { | ||
| const rsbuild = await createStubRsbuild({ | ||
| plugins: [pluginSplitChunks()], | ||
| it('should set `single-vendor` preset', async () => { | ||
| const rsbuild = await createRsbuild({ | ||
| config: { | ||
| performance: { | ||
| chunkSplit: { | ||
| strategy: 'split-by-size', | ||
| minSize: 1000, | ||
| maxSize: 5000, | ||
| }, | ||
| }, | ||
| output: { | ||
| polyfill: 'entry', | ||
| }, | ||
| splitChunks: { | ||
| preset: 'single-vendor', | ||
| }, | ||
| }, | ||
| }); | ||
|
|
||
| const config = await rsbuild.unwrapConfig(); | ||
| expect(config).toMatchSnapshot(); | ||
| const config = await rsbuild.initConfigs(); | ||
| expect(config[0].optimization?.splitChunks).toMatchSnapshot(); | ||
| }); | ||
|
|
||
| it('should set all-in-one config', async () => { | ||
| const rsbuild = await createStubRsbuild({ | ||
| plugins: [pluginSplitChunks()], | ||
| it('should disable split chunks', async () => { | ||
| const rsbuild = await createRsbuild({ | ||
| config: { | ||
| performance: { | ||
| chunkSplit: { | ||
| strategy: 'all-in-one', | ||
| }, | ||
| }, | ||
| output: { | ||
| polyfill: 'entry', | ||
| }, | ||
| splitChunks: false, | ||
| }, | ||
| }); | ||
|
|
||
| const config = await rsbuild.unwrapConfig(); | ||
| expect(config).toMatchSnapshot(); | ||
| const config = await rsbuild.initConfigs(); | ||
| expect(config[0].optimization?.splitChunks).toEqual(false); | ||
| }); | ||
|
|
||
| it('should set custom config', async () => { | ||
| const rsbuild = await createStubRsbuild({ | ||
| plugins: [pluginSplitChunks()], | ||
| it('should merge split chunks options', async () => { | ||
| const rsbuild = await createRsbuild({ | ||
| config: { | ||
| performance: { | ||
| chunkSplit: { | ||
| strategy: 'custom', | ||
| forceSplitting: [/react/], | ||
| splitChunks: { | ||
| cacheGroups: {}, | ||
| }, | ||
| }, | ||
| }, | ||
| output: { | ||
| polyfill: 'entry', | ||
| }, | ||
| }, | ||
| }); | ||
|
|
||
| const config = await rsbuild.unwrapConfig(); | ||
| expect(config).toMatchSnapshot(); | ||
| }); | ||
|
|
||
| it('should allow forceSplitting to be an object', async () => { | ||
| const rsbuild = await createStubRsbuild({ | ||
| plugins: [pluginSplitChunks()], | ||
| config: { | ||
| performance: { | ||
| chunkSplit: { | ||
| strategy: 'custom', | ||
| forceSplitting: { | ||
| axios: /axios/, | ||
| }, | ||
| splitChunks: { | ||
| cacheGroups: {}, | ||
| splitChunks: { | ||
| preset: 'default', | ||
| cacheGroups: { | ||
| commons: { | ||
| name: 'commons', | ||
| test: /[\\/]src[\\/]commons[\\/]/, | ||
| minChunks: 2, | ||
| priority: -10, | ||
| }, | ||
| }, | ||
| }, | ||
| output: { | ||
| polyfill: 'entry', | ||
| }, | ||
| }, | ||
| }); | ||
|
|
||
| const config = await rsbuild.unwrapConfig(); | ||
| expect(config).toMatchSnapshot(); | ||
| }); | ||
|
|
||
| it('should not split chunks when target is node', async () => { | ||
| const rsbuild = await createStubRsbuild({ | ||
| plugins: [pluginSplitChunks()], | ||
| config: { | ||
| output: { | ||
| target: 'node', | ||
| }, | ||
| }, | ||
| }); | ||
|
|
||
| const config = await rsbuild.unwrapConfig(); | ||
| expect(config).toMatchSnapshot(); | ||
| const config = await rsbuild.initConfigs(); | ||
| expect(config[0].optimization?.splitChunks).toMatchSnapshot(); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Missing test coverage for backward compatibility with the legacy performance.chunkSplit option. The code includes logic to support the deprecated performance.chunkSplit configuration (lines 293-306 in splitChunks.ts), but there are no tests to verify this backward compatibility works correctly.
Consider adding tests that verify:
- Legacy performance.chunkSplit still works when splitChunks is not explicitly set
- The deprecation warning is shown when both options are set
- The new splitChunks option takes precedence over the legacy option when both are present
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Summary
This PR introduces a new top-level
splitChunksoption in Rsbuild 2.0 and deprecates the legacyperformance.chunkSplitconfiguration.The goal is to align Rsbuild more closely with Rspack's
optimization.splitChunksconfig, while keeping a small set of Rsbuild-specific enhancements and preserving backward compatibility.Changes
splitChunksoption is added. It maps directly to Rspack'soptimization.splitChunks, with an extrapresetproperty.default,per-package,single-vendor.performance.chunkSplitoption are still supported but deprecated.Related Links
Checklist