Storybook 切换 framework 到 @storybook/nextjs-vite:从配置原理到迁移实战的完整指南
2026/9/8 20:31:58 网站建设 项目流程

Storybook 切换 framework 到 @storybook/nextjs-vite:从配置原理到迁移实战的完整指南

【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook

本文聚焦 Storybook 仓库中 nextjs-vite-add-framework.md 所演示的核心操作:把.storybook/main.js|ts中的framework属性切换到@storybook/nextjs-vite,并同步更新配置入口的类型导入(CSF 3 的StorybookConfig与 CSF Next 的defineMain两种风格)。读完后,你将能够独立完成 Next.js 项目从 Webpack 系框架(如@storybook/react-webpack5@storybook/nextjs)到 Vite 系框架的切换,并理解该配置项在 Storybook 内部到底驱动了哪些构建行为,以及切换后还需做哪些收尾工作。

一、这条配置改动到底在做什么

在 Next.js 项目的 Storybook 中,framework字段决定了“用什么框架预设来渲染组件、用什么构建器来打包”。切换到@storybook/nextjs-vite的完整改动如下(对应 nextjs-vite-add-framework.md 中的 diff 片段):

JavaScript 项目(.storybook/main.js,CSF 3):

export default { // ... - framework: '@storybook/react-webpack5', + framework: '@storybook/nextjs-vite', };

TypeScript 项目(.storybook/main.ts,CSF 3)——注意导入的类型来源也要同步更换

- import type { StorybookConfig } from '@storybook/your-previous-framework'; + import type { StorybookConfig } from '@storybook/nextjs-vite'; const config: StorybookConfig = { // ... - framework: '@storybook/react-webpack5', + framework: '@storybook/nextjs-vite', }; export default config;

新配置风格(CSF Next 实验性写法,defineMain从框架包的/node入口导入):

- import { defineMain } from '@storybook/your-previous-framework/node'; + import { defineMain } from '@storybook/nextjs-vite/node'; export default defineMain({ // ... - framework: '@storybook/react-webpack5', + framework: '@storybook/nextjs-vite', });

仓库源码可以佐证这两处导入的真实来源:

  1. /node入口确实存在。package.json 的exports字段声明了"./node": { "code": "./src/node/index.ts", ... },而 node/index.ts 的内容非常简洁——它只导出一个defineMain(config)函数,原样返回带@storybook/nextjs-vite类型约束的StorybookConfig对象:

    import type { StorybookConfig } from '../types.ts'; export function defineMain(config: StorybookConfig) { return config; }

    因此把defineMain的导入路径从旧框架换成@storybook/nextjs-vite/node,本质上是让main.ts里的frameworkcore.builder字段获得@storybook/nextjs-vite专属的类型约束。

  2. 类型层面也做了框架绑定。types.ts 中定义了FrameworkName = CompatibleString<'@storybook/nextjs-vite'>StorybookConfig类型要求framework只能是'@storybook/nextjs-vite'{ name, options }对象形式,且core.builder只能是@storybook/builder-vite。如果你把framework写错,TypeScript 会直接报错——这也是为什么 diff 里要求同步更换StorybookConfig的类型导入。

二、切换后的底层行为:preset 是如何工作的

仅改framework字段之所以能完成整个构建链的切换,是因为框架包通过 preset 预设接管了构建器与渲染器。查看 preset.ts 可以看到关键实现:

export const core: PresetProperty<'core'> = { builder: import.meta.resolve('@storybook/builder-vite'), renderer: import.meta.resolve('@storybook/react/preset'), };

从源码结构看:

  • core.builder指向@storybook/builder-vitecore.renderer指向@storybook/reactpreset——也就是说,framework: '@storybook/nextjs-vite'一句配置,实际等价于“Vite 构建器 + React 渲染器”的组合,这正是它与@storybook/nextjs(Webpack 5 构建器)的核心区别;
  • previewAnnotations会把@storybook/nextjs-vite/preview(以及 Next.js 16 以下的兼容版@storybook/nextjs-vite/config/preview)追加为 preview 注解,从而注入路由/导航桩、next/imagenext/font支持、next/head装饰器等 preview 层能力,这些能力无需用户额外注册;
  • viteFinal会先调用@storybook/react-vite/presetviteFinal拿到基础 React Vite 配置,然后在此基础上:自动归一化 PostCSS 配置(normalizePostCssConfig,从而支持你项目里的 Tailwind/PostCSS 定制)、把styled-jsx及其style子模块写入resolve.alias(零配置支持 styled-jsx)、最后追加vitePluginStorybookNextjs插件来处理nextConfigPath/image等框架选项。

三、framework 的 options 参数:切换时的进阶配置

types.ts 中的FrameworkOptions定义了切换framework时可同时传入的选项,写作对象形式:

export type FrameworkOptions = { /** The path to the Next.js configuration file. */ nextConfigPath?: string; image?: { includeFiles?: string[]; excludeFiles?: string[]; }; builder?: BuilderOptions; };

对应的.storybook/main.ts用法(取自 nextjs-vite.mdx 的 Options 一节):

import type { StorybookConfig } from '@storybook/nextjs-vite'; const config: StorybookConfig = { // ... framework: { name: '@storybook/nextjs-vite', options: { // 当 next.config.js 不在项目根目录时必须提供 nextConfigPath: '/path/to/your/next.config.js', }, }, }; export default config;

各选项的作用(结合 preset.ts 中options.presets.apply<FrameworkOptions>('frameworkOptions')的消费逻辑):

  • nextConfigPathstring):next.config.js的绝对路径。preset 会取它的dirname作为dir传给 Next.js 的 Vite 插件,用于定位你的 Next.js 项目结构;
  • imageobject):与 Vite 插件交互的图片处理选项(含includeFiles/excludeFiles过滤规则),决定哪些文件走next/image风格的导入转换;
  • builderRecord<string, any>):透传给@storybook/builder-vite的构建器选项,如test相关配置。

框架贡献的 stories 参数则在NextJsParameters中声明(同样见 types.ts):nextjs.appDirectoryboolean,默认falsenext/navigation组件故事需置true)、nextjs.navigationnext/navigation上下文覆盖)与nextjs.routernext/router上下文覆盖),可按 story / meta / 项目三级 parameters 继承。这些参数在切换到该框架后即可直接使用,是它与旧 Webpack 框架相比新增的运行时能力。

四、切换前后的收尾工作

framework字段只是迁移的一部分。nextjs-vite.mdx 的 “Manual migration” 章节(本文关联 diff 片段的实际使用处)指出了切换后必须核对的两件事:

  1. webpackFinalviteFinal:如果旧配置里存在自定义 Webpack 操作(webpackFinal),需要手工改写成等价的 Vite 配置(viteFinal)。注意并非所有 Webpack 修改可以原样照搬,需结合 Vite 的插件与 resolve 机制重写;
  2. .md文件导入:Webpack 时代直接import content from './doc.md'得到的字符串行为,在 Vite 下需要显式加?raw后缀。

此外,若你之前用独立的插件(addon)来集成 Next.js 的路由/导航能力,切换到该框架后这些能力已由框架内置,相关插件可以移除。

更稳妥的做法:automigrate 工具

如果你的旧框架是@storybook/nextjs,仓库内置了自动迁移工具,等价于上面所有手工步骤:

npx storybook automigrate nextjs-to-nextjs-vite

从 nextjs-to-nextjs-vite.ts 的源码可以确认它执行三步动作,与本文“Manual migration”完全对应:

  1. 更新所有package.json:移除@storybook/nextjs,按当前 Storybook 版本添加@storybook/nextjs-vite(若项目未装 Vite,还会补装vite@^7.0.0,见源码中的VITE_DEFAULT_VERSION);
  2. 改写.storybook/main.js|ts,用负向先行断言正则/@storybook\/nextjs(?!-vite)/g精确替换框架名,避免误伤已经是-vite的引用;
  3. 扫描 stories 与配置目录中的所有导入语句,把@storybook/nextjs的导入批量重写为@storybook/nextjs-vite

而本文关联文档覆盖的场景是从任意旧框架(示例中为@storybook/react-webpack5)切入@storybook/nextjs-vite,这类切换没有自动工具,需要按第一、二节的 diff 手工完成。

五、版本前提与验证清单

从 package.json 的peerDependencies可确认适用前提:next要求^14.1.0 || ^15.0.0 || ^16.0.0vite要求^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0,React 支持 16.8+ 至 19.x。切换完成后建议按以下清单验证:

  • framework字段与StorybookConfig/defineMain的导入源已同步为@storybook/nextjs-vite(TypeScript 项目若不同步,类型检查会报错);
  • 旧的webpackFinal已迁移为viteFinal.md导入已加?raw
  • 启动 dev server 后,next/imagenext/font、路由/导航桩与nextjs.*参数按预期工作(详见 nextjs-vite.mdx 各特性章节)。

参考路径

  • docs/_snippets/nextjs-vite-add-framework.md —— 本文关联的 framework 切换 diff 片段
  • docs/get-started/frameworks/nextjs-vite.mdx —— 该框架的完整文档(安装、配置、API、FAQ)
  • code/frameworks/nextjs-vite/src/preset.ts ——core/previewAnnotations/viteFinal预设实现
  • code/frameworks/nextjs-vite/src/node/index.ts ——defineMain入口
  • code/frameworks/nextjs-vite/src/types.ts ——StorybookConfigFrameworkOptionsNextJsParameters类型定义
  • code/lib/cli-storybook/src/automigrate/fixes/nextjs-to-nextjs-vite.ts —— 自动迁移工具实现

【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询