首页
/ Storybook 开源贡献实战:Monorepo 开发环境、沙盒调试与 CI 沙盒过滤

Storybook 开源贡献实战:Monorepo 开发环境、沙盒调试与 CI 沙盒过滤

2026-09-04 20:00:43作者:贡沫苏Truman

本文以 Storybook 仓库根目录的 CONTRIBUTING.md 为核心骨架,系统讲解贡献者如何从零搭建 Storybook 的本地开发环境:包括 Node.js 版本管理、monorepo 目录结构、yarn start 一键启动沙盒的原理、watch 模式增量构建指定包、Angular 代码的特殊构建要求,以及当 CI 中某个沙盒(sandbox)失败时如何聚焦调试。读完后,你可以独立完成一次针对 Storybook 源码的本地修改、验证与提交流程。

贡献方式与 AI 贡献规范

Storybook 欢迎任何形式的贡献,不限于代码。根据 CONTRIBUTING.md,贡献渠道包括:

  • 为功能请求创建 RFC(仓库内对应文档见 docs/contribute/RFC.mdx);
  • 更新文档,修正、改进或澄清现有说明(文档源码位于 docs/ 目录);
  • 为 Storybook 与各 JS 框架的集成添加新的代码片段示例(文档片段源码位于 docs/_snippets/ 目录);
  • 集成新的 JS 框架或改进现有框架支持(框架集成代码位于 code/frameworks/ 目录,见 docs/contribute/framework.mdx);
  • 编写 addon 扩展 Storybook 的功能(addon 源码位于 code/addons/ 目录);
  • 报告 Bug、在 GitHub Discussions 的 Help 分类回答他人问题、浏览并修复标注了 good first issue 的问题——这是快速上手的前端与文档类小任务。

文档中特别强调了一条 AI 贡献规范(“Never let an LLM speak for you”):

  • 团队允许把 AI 作为个人助理辅助贡献,但每个 issue 和 PR 背后必须有真实的人;
  • 所有 issue 和 PR 必须由真人使用官方模板创建,若 AI 辅助生成了 PR,需披露所用工具(如 Claude、Codex、Copilot);
  • 完全由 AI 自动生成、无人类参与(例如自动 agent 提交)的 PR/issue 会被维护者打标,3 天内无真人响应即自动关闭;
  • 对 issue、PR 或 Discussions 中无价值或包含错误信息的 AI 生成评论,维护者会隐藏,构成垃圾行为可能导致封禁。

此外,文档要求开始贡献前先阅读 CODE_OF_CONDUCT.md,并对流程有疑问时联系维护者。

前置条件:Node.js 版本与版本管理器

Storybook 的代码库针对 .nvmrc 文件中指定的 Node.js 版本进行开发。当前仓库中 .nvmrc 的内容为 22.22.3,即需要 Node.js 22 系列。文档推荐使用 fnm 作为版本管理器,配置步骤如下:

  1. 检查当前 Node.js 版本,并按所用工具切换:
# Check which version you're using
node --version
# node version manager
nvm use 22
# pnpm
pnpm env use --global 22
  1. 安装 fnm 并调整 shell 配置,加入以下四个关键参数:fnm envuse-on-cdcorepack-enabledversion-file-strategy recursive
eval "$(fnm env --use-on-cd --corepack-enabled --version-file-strategy recursive)"

其中 use-on-cd 表示进入目录时自动切换 Node 版本,version-file-strategy recursive 使 fnm 能向上递归查找 .nvmrc——这一点在 monorepo 中进入 code/ 等子目录时尤其有用。corepack-enabled 则配合仓库通过 packageManager 字段锁定的包管理器版本:根目录 package.json 中声明了 "packageManager": "yarn@4.18.0",即本仓库使用 Yarn 4(Berry)管理 workspace。

  1. Windows 用户需要启用 Windows Subsystem for Linux(WSL),并在 Windows 环境下以管理员权限的终端运行所有命令。

仓库结构:monorepo 全景

Storybook 采用 Yarn workspaces + Nx 的 monorepo 结构管理项目与各个包。根目录 package.jsonworkspaces.packages 字段声明了所有参与 workspace 的目录:agent-evalcodecode/addons/*code/builders/*code/corecode/frameworks/*code/lib/*code/presets/*code/renderers/*scripts

CONTRIBUTING.md 给出的目录概览(与当前仓库实际布局对照后,各目录职责如下):

.
├── CHANGELOG.md                  # 当前版本 Changelog
├── CHANGELOG.prerelease.md
├── CHANGELOG.v1-5.md
├── CHANGELOG.v6.md
├── CODEOWNERS
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING                  # 面向维护者的信息(如发布流程)
├── CONTRIBUTING.md               <--------- 你在这里!
├── LICENSE
├── MAINTAINERS.md
├── MIGRATION.md                  # 版本迁移指南
├── README.md
├── RESOLUTIONS.md
├── SECURITY.md
├── code                          # Storybook 代码库
│   ├── __mocks__
│   ├── addons                  # 内置 addon(a11y、docs、mcp、themes、vitest 等)
│   ├── builders                # builder-vite、builder-webpack5
│   ├── core                      # Storybook UI 与 API 的核心包
│   ├── e2e-internal             # 针对内部 Storybook UI 的 Playwright e2e 测试
│   ├── e2e-sandbox               # 针对生成沙盒的 Playwright e2e 测试
│   ├── frameworks                # 各框架-打包器组合(react-vite、vue3-vite、sveltekit…)
│   ├── lib                       # CLI(cli-sb、cli-storybook)与插件
│   ├── presets                   # 预设包(react-webpack、create-react-app、server-webpack)
│   ├── renderers                 # 各框架的 renderer(react、vue3、svelte、preact…)
│   ├── sandbox                   # 用于 Bug 复现或实验的沙盒模板清单
│   ├── playwright.config.ts
│   └── vitest.config.storybook.ts
├── codecov.yml
├── dependabot.yml
├── docs                          # 文档(mdx + 片段)
│   ├── _assets
│   ├── _snippets
│   ├── addons / api / builders / configure / contribute / essentials
│   ├── get-started / sharing / writing-docs / writing-stories / writing-tests
│   └── index.mdx
├── package.json                  # yarn monorepo 的根
├── nx.json                       # Nx 工作区配置
├── scripts                       # 构建与辅助脚本(task.ts、build-package.ts、ci/…)
├── test-storybooks               # 独立测试工程(ember-cli、mcp、yarn-pnp 等)
└── yarn.lock

值得注意的几个实际细节:

  • 版本信息:code/package.json 中当前版本为 10.6.0-beta.1,说明该快照处于 10.x 的 beta 周期;
  • 沙盒清单:code/sandbox/ 下每个目录(如 react-vite-default-tsnextjs-15-tssvelte-kit-skeleton-ts)只包含一个 template.json,描述该沙盒使用的框架、builder 与模板参数;
  • CI 配置由 scripts/ci/ 下的 TypeScript 生成(当前使用 CircleCI 配置生成器),而不是手写的静态 YAML。

Fork 仓库与配置 upstream

计划修改 Storybook 代码库时,应先 fork 仓库到你的 GitHub 账号,以便在本地修改后向主仓库提交 PR。同时把官方仓库添加为 upstream,确保可以随时 rebase 到主仓库最新变更:

git remote add upstream https://github.com/storybookjs/storybook.git
git fetch upstream
git branch --set-upstream-to upstream/main main

启动本地开发环境:yarn start 到底做了什么

开始贡献时,应在仓库根目录运行 yarn start。它会自动安装依赖、构建项目(包括各包)、并生成一个基于 React + TypeScript 的沙盒环境,其中带有一组测试 stories 供你快速上手:

# Navigate to the root directory of the Storybook repository
cd path/to/your/storybook/fork

# Install the required dependencies
yarn
# start the development environment
yarn start

从源码看,根 package.jsonstart 脚本的真实定义是:

"start": "yarn task --task dev --template react-vite/default-ts --start-from=install"

即它并非独立的启动逻辑,而是委托给仓库统一的任务运行器 scripts/task.ts。该运行器的工作机制包括:

  • 任务图与拓扑排序:所有任务(installcompilecheckpublishgeneratesandboxdevservetest-runnerchromatice2e-tests 等,见 scripts/task.ts 中的 tasks 对象)声明 dependsOn 依赖关系,运行器通过拓扑排序决定执行顺序;
  • 就绪检测与 startFrom:每个任务都有 ready() 方法判断产物是否已就绪;--start-from 可取 auto(CI 下默认)、task(只跑目标任务)、never(要求全链路就绪)或某个具体任务名(如 installpublish),从该任务起强制重跑,之前的产物被复用;
  • dev 是服务型任务dev 任务会启动并常驻服务,运行器在最终任务为 service 时保持进程打开直到 Ctrl-C;
  • 交互式选择:直接运行 yarn task 不带参数时,运行器会提示你选择模板(template)和任务(task),这正是后文“选择不同沙盒模板”功能的入口;
  • 模板来源:可选模板列表由 code/lib/cli-storybook/src/sandbox-templates.ts 导出,与 code/sandbox/ 目录下的 template.json 清单一一对应。

修改代码:watch 模式构建指定包

在沙盒运行期间修改 Storybook 各包源码时,需要在第二个终端中进入 code/ 目录并运行 watch 模式构建:

# Navigate to the code directory
cd path/to/your/storybook/fork/code

# Build the specified packages in watch mode
yarn build --watch react core-server api addon-docs

构建命令由 scripts/build-package.ts 实现,其行为与文档描述完全对应:

  • 包名规则:包名取发布包名去掉 @storybook/ 前缀后的部分(如 @storybook/reactreact@storybook/builder-vitebuilder-vite@storybook/addon-docsaddon-docs);storybook 包本身直接叫 storybook。脚本会为每个 workspace 生成对应的短名(suffix),命令行参数命中哪个短名就构建哪个包;
  • 无效包名提示:传入不存在的包名时,脚本会基于最接近匹配提示 “Did you mean xxx?” 并以非零码退出;
  • 无参数交互选择:不带包名时进入多选交互界面,可勾选 watch 模式与 production 模式;
  • 构建执行:每个选中的包会以 NODE_ENV=production 在各自目录下执行 scripts/build/build-package.ts 的构建入口,输出按包名着色区分。

构建完成后的验证方式分两种沙盒模式:

  1. linked 模式(默认):改动在刷新浏览器后即可看到;如果修改的是 server 侧包,可能需要重启沙盒;
  2. unlinked 模式:需要从 publish 步骤重新跑沙盒才能看到改动:
yarn task --task dev --template <your template> --start-from=publish

无论哪种模式,只要改动了 /code 或其他包内的代码,都应进入对应包目录运行 yarn test,确认改动没有破坏测试(仓库使用 Vitest,根 package.jsontest 脚本为 NODE_OPTIONS=--max_old_space_size=4096 vitest run)。

Angular 专用代码的构建要求

如果你在修改 Angular 相关代码,需要在上述命令后追加 --prod,以确保 Angular 编译器能正确拾取改动、不报错——即以生产模式构建所有包:

# Starts the build process in production mode
yarn task --prod

# Builds the specified packages in production mode
yarn build --prod --watch angular storybook addon-docs

--prod 参数在 scripts/build-package.ts 中通过 commander 的 --prod/--no-prod 选项解析,并透传给每个包的构建子进程。

针对不同沙盒模板进行调试

如果想换一个框架组合的沙盒来验证改动(例如 Vue3 + Vite 或 Next.js),直接运行 yarn task,运行器会交互式提示选择模板与任务:

yarn task --task dev --template vue3-vite/default-ts

可选模板即 code/sandbox/ 下的目录名(如 vue3-vite-default-tsnextjs-15-tssvelte-kit-skeleton-tsreact-webpack-18-ts 等),每个目录中的 template.json 描述了该沙盒的框架、builder 与参数。沙盒被生成到 code/sandbox/<模板名>/ 目录(运行器中 templateSandboxDir 的计算逻辑见 scripts/task.ts)。

聚焦调试 CI 中失败的沙盒

CI(尤其是 ci:daily workflow)会运行大量沙盒。当某个沙盒失败时,文档建议优先本地复现调试;若本地无法复现,可以强制 CI 只跑选定的沙盒子集。具体做法是在 CI 配置生成器中编辑过滤函数——当前仓库中对应位置为 scripts/ci/main.ts 中的 job 过滤逻辑:

/**
 * If you want to filter down to a particular job, e.g.for debugging purposes.. you can do that
 * here. You can filter on the `job.id` for example.
 * ...
 * @example
 * ```ts
 * const filteredTodos = todos.filter((job) => !!job.id.includes('qwik'));
 * ```
 */
const filteredJobs = jobs.filter((job) => !!job.id.includes('qwik'));

源码注释明确说明:可以按任意 job.id 过滤,例如只运行 test-runnere2evite 类沙盒;而且无需关心 requires 依赖字段,生成器内部的 ensureRequiredJobs 会自动补齐被过滤 job 所需的前置 job。过滤后若 job 数量减少,生成器会识别为“调试模式”。

故障排查

初始化过程抛错:如果运行 yarn start 时遇到如下错误,尝试第二次运行 yarn start

> NX ENOENT: no such file or directory, open 'storybook/code/node_modules/nx/package.json'

这是 Nx 在首次安装阶段解析自身包路径的已知时序问题,重跑通常即可解决。

Storybook 检测不到代码库变化:如果贡献过程中仍然遇到改动不生效的问题,建议先检查本地工作区是否混入了意外的本地变更。可运行:

git clean -dx --dry-run

该命令以 dry-run 方式列出如果加上 --force 将被删除的未跟踪/被忽略文件与目录。在真正执行带 --force 的命令之前,务必先提交需要保留的本地改动,否则这些内容会丢失。清理后重新执行 yarn start,让依赖与构建产物回到干净状态。

进一步阅读

整体而言,CONTRIBUTING.md 提供的是一条完整可复现的贡献流水线:fork + upstreamyarn start(等价于 yarn task --task dev --template react-vite/default-ts --start-from=install)→ 在 code/yarn build --watch <包名> 增量构建 → 刷新沙盒验证 → 包内 yarn test 保障 → 必要时切换沙盒模板或用 scripts/ci/main.ts 的过滤逻辑聚焦 CI 问题。这条流水线以任务图驱动的沙盒机制为核心,是深入 Storybook 源码的第一站。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
903
1.82 K
docsdocs
暂无描述
Markdown
888
5.78 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
527
590
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.51 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.33 K
1.45 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384
flutter_flutterflutter_flutter
本仓库是 Flutter SDK 与 Flutter Engine 的 OpenHarmony 适配版本,由 CPF-Flutter 团队维护。开发者可使用熟悉的 Flutter 技术栈开发 OpenHarmony 应用,3.35.7 及以后的适配版本可基于本仓库源码构建支持 OpenHarmony 的 Flutter Engine。
Dart
1.17 K
341