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 配置文件被写入的位置。