参与直播:周四美东时间上午 11 点,Storybook 9 发布及问答
文档
Storybook 文档

代码贡献

贡献新功能或错误修复至 Storybook 的 monorepo。本页概述了如何设置您的环境以贡献代码。

先决条件

  • 确保安装了 Node 18 版本(建议:v18.16.0)。
  • 如果您使用 Windows,所有命令都应在具有管理员权限的终端中运行。

初始设置

首先fork Storybook monorepo 并将其克隆到本地。

git clone https://github.com/your-username/storybook.git
cd storybook

Storybook 使用 Yarn 包管理器。使用 Corepack 设置正确的版本以与 Storybook 一起使用。

corepack enable

运行您的第一个沙盒

Storybook 的开发是在一组*沙盒*中进行的,这些沙盒是与不同用户设置对应的 Storybook 环境模板。在每个沙盒中,我们注入一组通用故事,以便在所有此类环境中测试核心功能和插件。

要在本地运行沙盒,可以使用 start 命令

yarn start

它将安装所需的先决条件,构建代码,基于 Vite React 设置创建并链接一个入门示例,最后启动 Storybook 服务器。

如果一切顺利,您应该看到沙盒正在运行。

Storybook sandbox running

运行不同的沙盒模板

默认情况下,start 命令配置为初始化基于 Vite 的 React 模板。如果您打算处理不同的渲染器,也可以这样做。首先运行 task 命令如下

yarn task

在提示时,请尽可能准确地回答问题,以便 Storybook 确定您的目标。回答这些问题后,如果您需要重新运行,应该会看到带有您选择的选项的整个命令。

yarn task 命令采取了一些开发快捷方式,这些快捷方式在切换分支时可能会让您措手不及,可能需要您重新运行 installcompile 任务。您可以通过使用 start-from=install 标志运行命令来加快此过程。

运行测试

成功运行您的第一个沙盒后,您应该已经在本地机器上构建了一个功能齐全的 Storybook 版本。在进行任何代码更改之前,验证所有内容是否正常工作至关重要——特别是测试套件。

运行以下命令执行测试

yarn test

开始开发

现在您已经验证了您的设置,是时候开始编码了。最简单的方法是在一个终端窗口中运行一个沙盒,并在单独的终端中运行交互式构建过程。

假设您仍在运行在运行 yarn start 命令后初始化的基于 Vite 的 React 沙盒,请打开一个新的终端窗口并导航到 Storybook monorepo 的 code 目录。然后,通过运行以下命令为您的贡献创建一个新分支

git checkout -b my-first-storybook-contribution

最后,运行构建过程,如下所示

yarn build

当提示在 watch 模式下启动构建过程时,回答yes 以进入交互模式开发。之后,选择要构建的包。例如,如果您想为 @storybook/addon-docs 开发一个功能,您可能希望同时选择 @storybook/addon-docsstorybook

构建的 watch 模式非常适合交互式开发。但是,出于性能原因,它只转译您的代码,而不执行 TypeScript 编译器。如果某项功能未按预期工作,请尝试启用 watch 模式运行 build 命令:它将为您重新生成 TypeScript 类型并执行自动类型检查。

Storybook package selector

如果您所做的工作影响了 Preview(Storybook 最内层的 iframe,显示故事的地方),它将在您保存后一到两秒自动刷新。

否则,如果影响了 Manager(Storybook 最外层的 iframe,显示插件的地方),您需要在保存后手动刷新。

Storybook manager preview

检查您的工作

完成编码后,适当地添加文档和测试。这样可以简化 PR 审查过程,这意味着您的代码将更快合并。

添加故事

在我们的套件中添加一个或一组通用故事有助于您测试您的工作。

假设您正在处理某个核心功能,很有可能已经存在一组完整的故事。检查该插件的 template/stories 目录,其中记录了它应该如何工作,并将您的故事添加到那里。

如果您正在修改与特定渲染器(例如,React、Vue 3 等)相关的内容,它也会有一个类似的 template/stories 目录,您需要在其中添加您的故事。

添加测试

单元测试确保 Storybook 不会意外中断。如果您的代码可能以不明显的方式出现回归,请在拉取请求中包含单元测试。使用以下命名约定

+-- parentFolder
|   +-- [filename].ts
|   +-- [filename].test.ts

端到端测试 (e2e)

Storybook 的 monorepo 设置为在 CI 期间依赖于使用 Playwright 进行端到端测试。为了帮助进行测试,我们鼓励您在提交贡献之前运行此测试套件。

要针对沙盒运行 e2e 测试,可以使用 e2e-tests 任务

yarn task --task e2e-tests --template=react-vite/default-ts --start-from=auto

如果出现问题并且您想调试它们,可以传递 DEBUG=1 环境变量,Playwright 将在 watch 模式下运行。

DEBUG=1 yarn task --task e2e-tests --template=react-vite/default-ts --start-from=auto

提交拉取请求

在提交您的贡献之前,最后一次运行测试套件,如下所示

yarn test

Storybook 依赖 Vitest 作为其测试套件的一部分。在测试运行期间,如果您发现快照测试失败,请使用 -u 标志重新运行命令以更新它们。

这样做可以防止最后时刻的 bug,并且是您提交拉取请求后更快合并贡献的好方法。否则,维护人员之一将标记拉取请求为 Work in Progress,直到所有测试通过。

目标 next 分支

测试套件完成后,是时候提交、推送并针对 Storybook 的 next(默认)分支开启拉取请求了。该分支是所有活跃开发进行的地方,并与最新的预发布版本相关联(例如,7.0.0-alpha.47)。

如果您的贡献侧重于错误修复,并且您希望它在下一个稳定版本中发布,请在拉取请求描述中提及。如果它看起来没有破坏性并修复了关键错误,我们将尝试打补丁。

使用 fork 时的有用资源

复现任务失败

创建 PR 后,如果 CI 任务之一失败,查看该任务的日志时,您会看到一条消息解释如何在本地复现该任务。通常这涉及针对正确的模板运行任务

yarn task --task e2e-tests --template=react-vite/default-ts --start-from=install

通常,最好从 install 任务开始,以确保您的本地代码完全最新。如果您复现了失败,可以尝试进行修复,使用 build 编译它们,然后使用 --start-from=auto 重新运行任务。

默认指令在“链接”模式下运行代码,这意味着 Storybook 库代码的构建更改将立即反映在沙盒中(下次您运行任务时)。但是,CI 在“未链接”模式下运行,在极少数情况下,行为会有所不同。

如果您在复现时遇到问题,请尝试使用 --no-link 标志重新运行命令。如果需要这样做,您需要在每次代码更改后使用 --start-from=compile 运行它。

如何处理复现

我们鼓励错误报告包含复现。就像可以在 monorepo 中针对示例项目交互式开发一样,也可以针对复现仓库进行开发。

要做到这一点,在 monorepo 的根目录下运行以下命令

npx storybook@next link https://github.com/your-username/your-project.git

此命令创建一个项目 ../storybook-repros/your-project,并自动将其链接到您的本地 Storybook 代码。连接后,您应该能够如上文所述运行 Storybook 并进行开发。

如果您已经在本地机器上有一个复现,您也可以使用 --local 标志将其链接到您的 monorepo 开发设置中

npx storybook@next link --local /path/to/local-repro-directory

storybook link 命令底层依赖于 Yarn linking。它要求您的本地复现也使用 Yarn 2 或更高版本,如果您已经根据我们的贡献指南使用 storybook sandbox 命令启用了它,情况就是如此。如果您尝试链接非 Yarn 2 项目,该过程将失败。

开发模板

第一步是在 code/lib/cli-storybook/src/sandbox-templates.ts 中添加一个条目,这是所有复现模板的主列表

'cra/default-js': {
    name: 'Create React App (Javascript)',
    script: 'npx create-react-app .',
    inDevelopment: true,
    expected: {
      framework: '@storybook/cra',
      renderer: '@storybook/react',
      builder: '@storybook/builder-webpack5',
    },
  },

在 PR 合并之前添加 inDevelopment 标志(您可以使用第二个 PR 快速跟进以删除该标志),因为这将使开发过程更容易。

key cra/default-js 由两部分组成

  • 前缀是用于生成复现应用程序的工具
  • 后缀是修改默认安装的选项,例如特定版本或选项

script 字段是生成应用程序环境的脚本。. 参数是“当前工作目录”,它是根据键自动生成的(例如 repros/cra/default-js/before-storybook)。也可以使用 {{beforeDir}} 键,它将被该目录的路径替换。

其余字段一目了然

存在 skipTasks 字段是因为某些沙盒可能暂时无法在特定任务中正常工作,但我们仍希望运行其他任务。例如,在我们无法控制的范围内引入了一个 bug,该 bug 只在 test-runner 任务中失败。

name 字段应包含模板的人类可读名称/描述。

expected 字段反映了我们期望 sb init 生成的框架/渲染器/构建器。这对于在生成沙盒时进行断言非常有用。例如,如果模板是使用不同的预期框架生成的,它将失败,从而作为检测回归的一种方式。

运行沙盒

如果您的模板具有 inDevelopment 标志,它将在沙盒过程中生成(本地)。您可以使用以下命令创建沙盒,其中 <template-key> 被所选模板的 ID 替换,例如 cra/default-js

yarn task --task dev --template <template-key> --start-from=install

带有 inDevelopment 的模板将自动使用 --no-link 标志运行,因为这是本地模板生成工作所必需的。

PR 合并后,模板将按夜间频率生成,您可以删除 inDevelopment 标志,沙盒将从我们的模板仓库拉取代码。

故障排除

yarn build --all --watch 会监视所有内容,但资源密集

提前知道您将更改哪些包很麻烦,并且监视它们的要求可能很高,即使在现代机器上也是如此。如果您使用的是性能足够强大的机器,可以使用 yarn build --all --watch 代替 yarn build

了解更多关于贡献 Storybook 的信息

  • RFC 流程,用于编写功能请求
  • 功能和错误修复的代码
  • 框架,用于入门新框架
  • 文档,用于文档改进、拼写错误和澄清
  • 示例,用于新片段