# Code splitting

A good chunk splitting strategy is important for improving application load performance. It leverages browser caching to reduce requests and improve loading speed.

Several [chunk splitting strategies](/guide/optimization/code-splitting.md) are built into Rsbuild to meet the needs of most applications. You can also customize chunk splitting configuration for specific use cases.

> See [Rspack - Code Splitting](https://rspack.rs/guide/optimization/code-splitting) for more details.

## Strategies

> The chunk splitting configuration of Rsbuild is in [performance.chunkSplit](/config/performance/chunk-split.md).

Rsbuild supports the following chunk splitting strategies:

* `split-by-experience`: an empirical splitting strategy that automatically splits some commonly used npm packages into chunks of moderate size.
* `split-by-module`: split by npm package granularity, where each npm package corresponds to a chunk.
* `split-by-size`: automatically split based on module size.
* `all-in-one`: bundle all code into one chunk.
* `single-vendor`: bundle all npm packages into a single chunk.
* `custom`: custom chunk splitting strategy.

::: tip
When using strategies other than `all-in-one`, Rspack's default splitting rules will also take effect. For more details, see [Rspack - SplitChunksPlugin](https://rspack.rs/plugins/webpack/split-chunks-plugin#default-behavior).
:::

## split-by-experience

### Behavior

Rsbuild uses the `split-by-experience` strategy by default, an optimization strategy based on practical experience. When your application uses the following npm packages, they're automatically split into separate chunks:

* `lib-polyfill.js`: Contains `core-js`, `@swc/helpers`, `tslib`
* `lib-axios.js`: Contains `axios`
* `lib-react.js`: Provided by [@rsbuild/plugin-react](/plugins/list/plugin-react.md#splitchunks)
* `lib-vue.js`: Provided by [@rsbuild/plugin-vue](/plugins/list/plugin-vue.md#splitchunks)

This approach groups commonly used packages and splits them into individual chunks, improving browser caching efficiency.

### Config

```ts
export default {
  performance: {
    chunkSplit: {
      strategy: 'split-by-experience',
    },
  },
};
```

### Notes

If the npm packages mentioned above aren't installed or used, the corresponding chunks won't be generated.

## split-by-module

### Behavior

Split each npm package into a separate chunk.

::: warning
This strategy splits node\_modules with the finest granularity. Under HTTP/2, multiplexing can speed up resource loading. However, in non-HTTP/2 environments, use this strategy cautiously due to HTTP head-of-line blocking.
:::

### Config

```ts
export default {
  performance: {
    chunkSplit: {
      strategy: 'split-by-module',
    },
  },
};
```

### Notes

* This configuration splits node\_modules into many smaller chunks, resulting in many file requests.
* With HTTP/2, resource loading accelerates and cache hit rates improve due to multiplexing.
* Without HTTP/2, page loading performance may degrade due to HTTP head-of-line blocking. Use with caution.

## all-in-one

### Behavior

This strategy puts all source code and third-party dependencies in a single chunk.

### Config

```ts
export default {
  performance: {
    chunkSplit: {
      strategy: 'all-in-one',
    },
  },
};
```

### Notes

* This configuration bundles all generated JS code into a single file (except dynamically imported chunks).
* The single JS file may be very large, potentially reducing page loading performance.

To also bundle dynamically imported chunks into a single file, set the [output.asyncChunks](https://rspack.rs/config/output#outputasyncchunks) option in Rspack to `false`:

```js
export default defineConfig({
  performance: {
    chunkSplit: {
      strategy: 'all-in-one',
    },
  },
  tools: {
    rspack: {
      output: {
        asyncChunks: false,
      },
    },
  },
});
```

## single-vendor

### Behavior

This strategy puts third-party dependencies in one chunk and source code in another.

### Config

```ts
export default {
  performance: {
    chunkSplit: {
      strategy: 'single-vendor',
    },
  },
};
```

### Notes

The single vendor file may be very large, potentially reducing page loading performance.

## split-by-size

### Behavior

With this strategy, after setting `minSize` and `maxSize` to fixed values, Rsbuild will automatically split chunks without extra configuration.

### Config

```ts
export default {
  performance: {
    chunkSplit: {
      strategy: 'split-by-size',
      minSize: 30000,
      maxSize: 50000,
    },
  },
};
```

## Custom splitting strategy

Beyond the built-in strategies, you can customize the splitting strategy for specific needs. Custom strategies have two parts:

* Custom group
* Custom Rspack `splitChunks` config

You can combine these custom capabilities with built-in strategies: use built-in strategies for common packages and custom functions for other packages.

### Custom group

Rsbuild supports custom groups, which are more flexible than built-in strategies and simpler than writing Rspack's `splitChunks` config.

For example, split the `axios` library under node\_modules into `axios.js`:

```js
export default {
  performance: {
    chunkSplit: {
      forceSplitting: {
        axios: /node_modules[\\/]axios/,
      },
    },
  },
};
```

Using the `forceSplitting` config, you can easily split packages into chunks.

#### Notes

Chunks split using `forceSplitting` are inserted into the HTML file as initial resources using `<script>` tags. Split them appropriately based on your scenario to avoid excessive initial bundle size.

### Custom config

Beyond custom grouping, you can customize Rspack's `splitChunks` config using `override`. For example:

* Set `minSize` to 30,000 so modules smaller than 30,000 bytes will not be split.

```ts
export default {
  performance: {
    chunkSplit: {
      override: {
        chunks: 'all',
        minSize: 30000,
      },
    },
  },
};
```

* Bundle all CSS files into a single `styles.css`.

```ts
export default {
  performance: {
    chunkSplit: {
      override: {
        cacheGroups: {
          styles: {
            name: 'styles',
            minSize: 0,
            chunks: 'all',
            test: /\.(?:css|less|sass|scss|styl)$/,
            priority: 99,
          },
        },
      },
    },
  },
};
```

The `override` config will be merged with Rspack's `splitChunks` config. For specific config details, see [Rspack - splitChunks](https://rspack.rs/config/optimization#optimizationsplitchunks).

## Using dynamic import for code splitting

Beyond the `chunkSplit` configuration, [dynamic import](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import) is another important optimization technique that can effectively reduce initial bundle size.

:::tip About dynamic import
Dynamic import, introduced in ECMAScript 2020, allows you to load JavaScript modules dynamically. Rspack supports dynamic import by default, so you can use it directly in your code.
:::

When the bundler encounters `import()` syntax, it automatically splits the relevant code into a new chunk and loads it on-demand at runtime.

For example, if your project has a large module called `bigModule.ts` (which can also be a third-party dependency), you can use dynamic import to load it on-demand:

```js
// Somewhere in your code where you need to use bigModule
import('./bigModule.ts').then((bigModule) => {
  // Use bigModule here
});
```

When you run the build command, `bigModule.ts` will be automatically split into a new chunk and loaded on-demand at runtime.
