close

Migration

This guide covers migrating an existing Storybook project from the webpack5 or Vite framework to Storybook Rsbuild (e.g. storybook-react-rsbuild).

Using an AI coding agent?

Your agent can handle this migration automatically. Install the agent skills and ask it to migrate your project:

npm
yarn
pnpm
bun
deno
npx skills add rstackjs/agent-skills --skill storybook-rsbuild
Storybook versions

Match your Storybook version to the correct storybook-rsbuild release:

StorybookStorybook Rsbuild
v10^3
v9^2
v8^1

From Storybook Webpack5 Framework

If your .storybook/main.ts uses a webpack5 framework package (e.g. @storybook/react-webpack5, @storybook/vue3-webpack5), follow this section.

1. Replace packages

Uninstall the old webpack5 framework package, and install the Rsbuild equivalent along with @rsbuild/core.

For example, to migrate a React project:

npm
yarn
pnpm
bun
deno
npm install @rsbuild/core storybook-react-rsbuild -D

Then remove the old packages:

npm
yarn
pnpm
bun
deno
npm remove @storybook/builder-webpack5 @storybook/react-webpack5

The framework package (e.g. storybook-react-rsbuild) includes storybook-builder-rsbuild as a dependency — you do not need to install the builder separately.

Package mapping

Old (webpack5)New (Rsbuild)
@storybook/react-webpack5storybook-react-rsbuild
@storybook/vue3-webpack5storybook-vue3-rsbuild
@storybook/html-webpack5storybook-html-rsbuild
@storybook/web-components-webpack5storybook-web-components-rsbuild

2. Update .storybook/main.ts

.storybook/main.ts
// Before
// import type { StorybookConfig } from '@storybook/react-webpack5'
// After
import type { 
import StorybookConfig
StorybookConfig
} from 'storybook-react-rsbuild'
const
const config: StorybookConfig
config
:
import StorybookConfig
StorybookConfig
= {
// Before: framework: '@storybook/react-webpack5',
framework: string
framework
: 'storybook-react-rsbuild',
stories: string[]
stories
: ['../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
} export default
const config: StorybookConfig
config

3. Convert webpackFinal to rsbuildFinal

Use

mergeRsbuildConfig for modifications Always use mergeRsbuildConfig from @rsbuild/core to modify the config. Directly mutating properties like config.tools.rspack = {...} may not work because internal configs can be arrays of functions/objects, and direct assignment may be silently ignored.

.storybook/main.ts
import type { 
import StorybookConfig
StorybookConfig
} from 'storybook-react-rsbuild'
import {
import mergeRsbuildConfig
mergeRsbuildConfig
} from '@rsbuild/core'
const
const config: StorybookConfig
config
:
import StorybookConfig
StorybookConfig
= {
framework: string
framework
: 'storybook-react-rsbuild',
stories: never[]
stories
: [],
// Before: // webpackFinal: async (config) => { // config.resolve.alias['@components'] = path.resolve(__dirname, '../src/components') // config.module.rules.push({ test: /\.svg$/, use: ['@svgr/webpack'] }) // return config // }, // After:
rsbuildFinal: (config: any) => Promise<any>
rsbuildFinal
: async (
config: any
config
) => {
return
import mergeRsbuildConfig
mergeRsbuildConfig
(
config: any
config
, {
source: {
    alias: {
        '@components': string;
    };
}
source
: {
alias: {
    '@components': string;
}
alias
: {
'@components': './src/components', }, }, // For SVG, use @rsbuild/plugin-svgr }) }, } export default
const config: StorybookConfig
config

4. Handle webpack-dependent addons

Some Storybook addons use webpackFinal internally. Move them from addons to webpackAddons:

.storybook/main.ts
import type { 
import StorybookConfig
StorybookConfig
} from 'storybook-react-rsbuild'
const
const config: StorybookConfig
config
:
import StorybookConfig
StorybookConfig
= {
framework: string
framework
: 'storybook-react-rsbuild',
stories: never[]
stories
: [],
// Regular addons (framework-agnostic)
addons: string[]
addons
: [
'@storybook/addon-docs', '@storybook/addon-onboarding', ], // Addons that depend on webpack loaders/plugins
webpackAddons: string[]
webpackAddons
: [
'@storybook/addon-coverage', ], } export default
const config: StorybookConfig
config

The webpackAddons field runs each addon's webpackFinal hook and translates the resulting webpack config into Rspack config automatically.

5. Convert common webpack patterns

webpack patternRsbuild equivalent
config.resolve.aliassource.alias in rsbuildFinal
config.resolve.extensionssource.extensions (Rsbuild has sensible defaults)
config.module.rules (loaders)tools.rspack or Rsbuild plugins
config.plugins (webpack plugins)tools.rspack for Rspack plugins
DefinePluginsource.define
css-loader / style-loaderBuilt-in, use tools.cssLoader if customizing
sass-loader@rsbuild/plugin-sass
less-loader@rsbuild/plugin-less
file-loader / url-loaderBuilt-in asset modules
SVGR@rsbuild/plugin-svgr
Rspack plugin compatibility

Not all webpack plugins are compatible with Rspack. Check the Rspack compatibility guide for details.


From Storybook Vite Framework

If your .storybook/main.ts uses a Vite framework package (e.g. @storybook/react-vite, @storybook/vue3-vite), follow this section.

1. Replace packages

Uninstall the old Vite framework package, and install the Rsbuild equivalent along with @rsbuild/core.

For example, to migrate a React project:

npm
yarn
pnpm
bun
deno
npm install @rsbuild/core storybook-react-rsbuild -D

Then remove the old packages:

npm
yarn
pnpm
bun
deno
npm remove @storybook/builder-vite @storybook/react-vite

Package mapping

Old (Vite)New (Rsbuild)
@storybook/react-vitestorybook-react-rsbuild
@storybook/vue3-vitestorybook-vue3-rsbuild
@storybook/html-vitestorybook-html-rsbuild
@storybook/web-components-vitestorybook-web-components-rsbuild

2. Update .storybook/main.ts

.storybook/main.ts
// Before
// import type { StorybookConfig } from '@storybook/react-vite'
// After
import type { 
import StorybookConfig
StorybookConfig
} from 'storybook-react-rsbuild'
const
const config: StorybookConfig
config
:
import StorybookConfig
StorybookConfig
= {
// Before: framework: '@storybook/react-vite',
framework: string
framework
: 'storybook-react-rsbuild',
stories: string[]
stories
: ['../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'],
} export default
const config: StorybookConfig
config

3. Convert viteFinal to rsbuildFinal

.storybook/main.ts
import type { 
import StorybookConfig
StorybookConfig
} from 'storybook-react-rsbuild'
import {
import mergeRsbuildConfig
mergeRsbuildConfig
} from '@rsbuild/core'
const
const config: StorybookConfig
config
:
import StorybookConfig
StorybookConfig
= {
framework: string
framework
: 'storybook-react-rsbuild',
stories: never[]
stories
: [],
// Before: // viteFinal: async (config) => { // config.resolve.alias['@'] = path.resolve(__dirname, '../src') // return config // }, // After:
rsbuildFinal: (config: any) => Promise<any>
rsbuildFinal
: async (
config: any
config
) => {
return
import mergeRsbuildConfig
mergeRsbuildConfig
(
config: any
config
, {
source: {
    alias: {
        '@': string;
    };
}
source
: {
alias: {
    '@': string;
}
alias
: {
'@': './src', }, }, }) }, } export default
const config: StorybookConfig
config

4. Convert common Vite patterns

Vite patternRsbuild equivalent
resolve.aliassource.alias in rsbuildFinal
plugins: [react()]Auto-configured by framework package
css.preprocessorOptions@rsbuild/plugin-sass or @rsbuild/plugin-less
definesource.define
server.proxyserver.proxy
build.targetoutput.target
Vite plugins are not compatible

Vite plugins cannot be used with Rsbuild. Find equivalent Rsbuild plugins at the Rsbuild plugin list.


Verification

After migration, verify:

  1. npx storybook dev starts without errors
  2. All stories render correctly
  3. HMR works (edit a component, see it update)
  4. npx storybook build completes successfully
  5. Addons function correctly (especially docs, controls, actions)

Debugging

Enable Rsbuild debug mode to inspect the generated config:

DEBUG=rsbuild storybook dev

Check the CLI output to see where the Rsbuild and Rspack configs are written.