close

迁移

本指南介绍如何将现有的 Storybook 项目从 webpack5Vite framework 迁移到 Storybook Rsbuild(例如 storybook-react-rsbuild)。

Using an AI coding agent?

你的 agent 可以自动完成此次迁移。安装 agent skills 并让它迁移你的项目:

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

请将你的 Storybook 版本与对应的 storybook-rsbuild 版本匹配:

StorybookStorybook Rsbuild
v10^3
v9^2
v8^1

从 Storybook Webpack5 Framework 迁移

如果你的 .storybook/main.ts 使用了 webpack5 framework 包(例如 @storybook/react-webpack5@storybook/vue3-webpack5),请按照本节操作。

1. 替换包

卸载旧的 webpack5 framework 包,并安装对应的 Rsbuild 版本以及 @rsbuild/core

例如,迁移一个 React 项目:

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

然后移除旧的包:

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

framework 包(例如 storybook-react-rsbuild)已将 storybook-builder-rsbuild 作为依赖项包含在内——你无需单独安装 builder。

包映射关系

旧(webpack5)新(Rsbuild)
@storybook/react-webpack5storybook-react-rsbuild
@storybook/vue3-webpack5storybook-vue3-rsbuild
@storybook/html-webpack5storybook-html-rsbuild
@storybook/web-components-webpack5storybook-web-components-rsbuild

2. 更新 .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. 将 webpackFinal 转换为 rsbuildFinal

Use

mergeRsbuildConfig for modifications 请始终使用来自 @rsbuild/coremergeRsbuildConfig 来修改配置。直接修改 config.tools.rspack = {...} 这类属性可能不会生效,因为内部配置可能是由函数/对象组成的数组,直接赋值可能会被静默忽略。

.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
, {
resolve: {
    alias: {
        '@components': string;
    };
}
resolve
: {
alias: {
    '@components': string;
}
alias
: {
'@components': './src/components', }, }, // For SVG, use @rsbuild/plugin-svgr }) }, } export default
const config: StorybookConfig
config
Use relative paths in

resolve.alias Rsbuild 会相对于项目根目录解析 alias 值。请使用 './src/components',而不是 path.resolve(__dirname, '../src/components')。相对路径写法更简洁,并且能避免 ESM 配置中 __dirname 带来的问题。

4. 处理依赖 webpack 的 addon

部分 Storybook addon 在内部使用了 webpackFinal。请将它们从 addons 移动到 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

webpackAddons 字段会运行每个 addon 的 webpackFinal 钩子,并自动将生成的 webpack 配置转换为 Rspack 配置。

Common addons that need

webpackAddons 有一些 addon 在内部挂载了 webpackFinal,必须移动到 webpackAddons(或替换为 Rsbuild 原生等价方案):

  • @storybook/addon-styling-webpack —— 全局 CSS / PostCSS / Sass / Less。可通过 webpackAddons 接入,或替换为 @rsbuild/plugin-postcss@rsbuild/plugin-sass@rsbuild/plugin-less
  • @storybook/addon-coverage —— 收集测试覆盖率;通过 webpackAddons 接入。
  • @storybook/preset-create-react-app —— CRA 兼容性;通过 webpackAddons 接入。

如果某个 addon 的名称以 -webpack 结尾,或其文档提到了 webpackFinal,则可以认为它需要这样处理。即使 storybook build 仍然通过,静默丢弃一个仅支持 webpack 的 addon 也是一种功能退化。

5. 转换常见的 webpack 模式

webpack 模式Rsbuild 等价方案
config.resolve.aliasrsbuildFinal 中的 resolve.alias
config.resolve.extensionsresolve.extensions(Rsbuild 已有合理的默认值)
config.module.rules(loaders)tools.rspack 或 Rsbuild plugins
config.plugins(webpack plugins)对于 Rspack plugins 使用 tools.rspack
DefinePluginsource.define
css-loader / style-loader内置支持,如需自定义可使用 tools.cssLoader
sass-loader@rsbuild/plugin-sass
less-loader@rsbuild/plugin-less
file-loader / url-loader内置 asset modules
SVGR@rsbuild/plugin-svgr
Rspack plugin compatibility

并非所有 webpack plugin 都与 Rspack 兼容。详情请查阅 Rspack 兼容性指南


从 Storybook Vite Framework 迁移

如果你的 .storybook/main.ts 使用了 Vite framework 包(例如 @storybook/react-vite@storybook/vue3-vite),请按照本节操作。

1. 替换包

卸载旧的 Vite framework 包,并安装对应的 Rsbuild 版本以及 @rsbuild/core

例如,迁移一个 React 项目:

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

然后移除旧的包:

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

包映射关系

旧(Vite)新(Rsbuild)
@storybook/react-vitestorybook-react-rsbuild
@storybook/vue3-vitestorybook-vue3-rsbuild
@storybook/html-vitestorybook-html-rsbuild
@storybook/web-components-vitestorybook-web-components-rsbuild

2. 更新 .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. 将 viteFinal 转换为 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
, {
resolve: {
    alias: {
        '@': string;
    };
}
resolve
: {
alias: {
    '@': string;
}
alias
: {
'@': './src', }, }, }) }, } export default
const config: StorybookConfig
config
Use relative paths in

resolve.alias Rsbuild 会相对于项目根目录解析 alias 值。请使用 './src',而不是 path.resolve(__dirname, '../src')。相对路径写法更简洁,并且能避免 ESM 配置中 __dirname 带来的问题。

4. 转换常见的 Vite 模式

Vite 模式Rsbuild 等价方案
resolve.aliasrsbuildFinal 中的 resolve.alias
plugins: [react()]由 framework 包自动配置
css.preprocessorOptions@rsbuild/plugin-sass@rsbuild/plugin-less
definesource.define
server.proxyserver.proxy
build.targetoutput.target
Vite plugins are not compatible

Vite plugin 无法与 Rsbuild 一起使用。请在 Rsbuild plugin 列表 中查找等价的 Rsbuild plugin。


验证

迁移完成后,请验证:

  1. npx storybook dev 能够无错误启动
  2. 所有 stories 都能正确渲染
  3. HMR 正常工作(编辑某个组件,能看到它更新)
  4. npx storybook build 能够成功完成
  5. addon 功能正常(尤其是 docs、controls、actions)

调试

启用 Rsbuild 调试模式以检查生成的配置:

DEBUG=rsbuild storybook dev

查看 CLI 输出,确认 Rsbuild 和 Rspack 配置文件被写入的位置。