Docs
Storybook Docs

代码贡献

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

¥Contribute a new feature or bug fix to Storybook's monorepo. This page outlines how to get your environment set up to contribute code.

先决条件

¥Prerequisites

  • 确保你已安装 Node 版本 18(建议:v18.16.0)。

    ¥Ensure you have Node version 18 installed (suggestion: v18.16.0).

  • 如果你使用的是 Windows,请确保使用适用于 Linux 的 Windows 子系统 (WSL)。

    ¥Ensure if you are using Windows to use the Windows Subsystem for Linux (WSL).

初始设置

¥Initial setup

首先 forking Storybook monorepo 并在本地克隆。

¥Start by forking the Storybook monorepo and cloning it locally.

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

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

¥Storybook uses the Yarn package manager. Use Corepack to set up the correct version for use with Storybook.

corepack enable

运行你的第一个沙盒

¥Run your first sandbox

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

¥Storybook development happens in a set of sandboxes which are templated Storybook environments corresponding to different user setups. Within each sandbox, we inject a set of generalized stories that allow us to test core features and addons in all such environments.

要在本地运行沙箱,你可以使用 start 命令:

¥To run a sandbox locally, you can use the start command:

yarn start

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

¥It will install the required prerequisites, build the code, create and link a starter example based on a Vite React setup and finally start the Storybook server.

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

¥If all goes well, you should see the sandbox running.

Storybook sandbox running

运行不同的沙盒模板

¥Running a different sandbox template

默认情况下,start 命令配置为初始化基于 Vite 的 React 模板。如果你打算改用其他渲染器,你也可以这样做。首先运行 task 命令,如下所示:

¥By default, the start command is configured to initialize a Vite-based React template. If you're planning on working on a different renderer instead, you can do so as well. Start by running the task command as follows:

yarn task

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

¥When prompted, answer the questions as accurately as possible to allow Storybook to determine your goals. After answering these questions, you should see the entire command with the options you've selected should you require to re-run it.

yarn task 命令采用了一些开发捷径,在切换分支时可能会让你措手不及,并且可能需要你重新运行 installcompile 任务。你可以通过运行带有 start-from=install 标志的命令来加快该过程。

¥The yarn task command takes a few development shortcuts that can catch you off guard when switching branches and may require you to re-run both the install and compile tasks. You can speed up the process by running the command with the start-from=install flag.

运行测试

¥Running tests

成功运行 第一个沙箱 后,你应该在本地机器上构建一个功能齐全的 Storybook 版本。在进行任何代码更改之前,验证一切是否正常工作至关重要 - 特别是测试套件。

¥After successfully running your first sandbox, you should have a fully functional Storybook version built on your local machine. Before jumping onto any code changes, verifying everything is working is essential—specifically, the test suite.

运行以下命令来执行测试:

¥Run the following command to execute the tests:

yarn test

开始开发

¥Start developing

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

¥Now that you've verified your setup, it's time to jump into code. The simplest way is to run one of the sandboxes in one terminal window and the interactive build process in a separate terminal.

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

¥Assuming you're still running the Vite-based React sandbox initialized after running the yarn start command, open a new terminal window and navigate to the code directory of the Storybook monorepo. Then, create a new branch for your contribution by running the following command:

git checkout -b my-first-storybook-contribution

最后,使用以下命令运行构建过程:

¥Lastly, run the build process with the following:

yarn build

当提示以 watch 模式启动构建过程时,回答“是”以在交互模式下进行开发。之后,选择要构建的包。例如,如果你要开发 @storybook/addon-docs 的功能,你可能想要同时选择 @storybook/addon-docs@storybook/components

¥When prompted to start the build process in watch mode, answer yes to develop in interactive mode. Afterward, choose which packages you want to build. For example, if you're going to work on a feature for @storybook/addon-docs, you might want to select both @storybook/addon-docs and @storybook/components.

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

¥Build's watch mode is great for interactive development. However, for performance reasons, it only transpiles your code and doesn't execute the TypeScript compiler. If something isn't working as expected, try running the build command WITHOUT enabling watch mode: it will re-generate TypeScript types and perform automatic type checking for you.

Storybook package selector

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

¥If the work you'll be doing affects the Preview (the innermost Storybook iframe, where the stories are displayed), it will automatically refresh one to two seconds after you save.

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

¥Otherwise, if it affects the Manager (the outermost Storybook iframe where the addons are displayed), you'll need to refresh manually after saving.

Storybook manager preview

检查你的工作

¥Check your work

当你完成编码后,请根据需要添加文档和测试。这简化了 PR 审查流程,这意味着你的代码将更快地合并。

¥When you're done coding, add documentation and tests as appropriate. That simplifies the PR review process, which means your code will get merged faster.

添加故事

¥Add stories

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

¥Adding a story or set of generic stories to our suite helps you test your work.

假设你正在处理 基本插件 之一,那么很可能已经存在一整套故事。检查插件的 template/stories 目录,该目录记录了它应该如何工作,并在其中添加你的故事。

¥Assuming you're working on one of the Essential addons, there's a chance that a complete set of stories already exists. Check the addon's template/stories directory that documents how it's supposed to work and add your stories there.

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

¥If you're modifying something related to a specific renderer (e.g., React, Vue 3, etc.), it will also have a similar template/stories directory in which you'll need to add your stories.

添加测试

¥Add tests

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

¥Unit tests ensure that Storybook doesn't break accidentally. If your code can regress in non-obvious ways, include unit tests with your pull request. Use the following naming convention:

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

端到端测试(e2e)

¥End-to-end tests (e2e)

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

¥Storybook's monorepo is set up to rely on end-to-end testing with Playwright during CI. To help with testing, we encourage running this test suite before submitting your contribution.

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

¥To run an e2e test against a sandbox, you can use the e2e-tests task:

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

如果有问题并且你想调试它们,你可以传递 DEBUG=1 环境变量,Playwright 将以监视模式运行。

¥If there are issues and you'd like to debug them, you can pass a DEBUG=1 environment variable, and Playwright will run in watch mode.

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

提交拉取请求

¥Submit a pull request

在提交你的贡献之前,请使用以下命令最后一次运行测试套件:

¥Before submitting your contribution, run the test suite one last time with the following:

yarn test

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

¥Storybook relies on Vitest as part of it's testing suite. During the test run, if you spot that snapshot tests are failing, re-run the command with the -u flag to update them.

这样做可以防止最后一刻出现错误,并且是提交拉取请求后更快地合并贡献的好方法。如果不这样做,将导致其中一位维护者使用“正在进行的工作”标签标记拉取请求,直到所有测试通过。

¥Doing this prevents last-minute bugs and is a great way to merge your contribution faster once you submit your pull request. Failing to do so will lead to one of the maintainers mark the pull request with the Work in Progress label until all tests pass.

目标 next 分支

¥Target next branch

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

¥Once the test suite finishes, it's time to commit, push and open a pull request against Storybook's next (default) branch. This branch is where all active development happens and is associated with the latest prerelease version (e.g., 7.0.0-alpha.47).

如果你的贡献侧重于错误修复,并且你希望它在下一个稳定版本中出现,请在拉取请求描述中提及它。如果它看起来没有破坏性并修复了关键错误,我们会尝试对其进行修补。

¥If your contribution focuses on a bugfix and you want it featured in the next stable release, mention it in the pull request description. We'll try to patch it if it appears non-disruptive and fixes a critical bug.

使用 fork 时有用的资源

¥Useful resources when working with forks

重现作业失败

¥Reproducing job failures

创建 PR 后,如果其中一个 CI 作业失败,则在检查该作业的日志时,你将看到它打印了一条消息,解释如何在本地重现该任务。通常这涉及针对正确的模板运行任务:

¥After creating your PR, if one of the CI jobs failed, when checking the logs of that job, you will see that it printed a message explaining how to reproduce the task locally. Typically that involves running the task against the right template:

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

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

¥Typically it is a good idea to start from the install task to ensure your local code is completely up to date. If you reproduce the failure, you can try and make fixes, compile them with build, then rerun the task with --start-from=auto.

默认指令以 "linked" 模式运行代码,这意味着对 Storybook 库代码的构建更改将立即反映在沙箱中(下次运行任务时)。但是,CI 在 "unlinked" 模式下运行,在极少数情况下,其行为会有所不同。

¥The default instructions run the code in "linked" mode, meaning built changes to Storybook library code will be reflected in the sandbox immediately (the next time you run the task). However, CI runs in "unlinked" mode, which in rare cases, will behave differently.

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

¥If you are having trouble reproducing, try rerunning the command with the --no-link flag. If you need to do that, you'll need to run it with --start-from=compile after each code change.

如何使用复制品

¥How to work with reproductions

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

¥We encourage bug reports to include reproductions. In the same way that it's possible to develop interactively against example projects in the monorepo, it's also possible to develop against a reproduction repository.

为此,请在 monorepo 的根目录中运行以下命令:

¥To do so, run the following command in the root of the monorepo:

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

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

¥This command creates a project ../storybook-repros/your-project, and automatically links it to your local Storybook code. After connecting it, you should be able to run Storybook and develop as mentioned above.

如果你已经在本地机器上进行了复制,你可以类似地使用 --local 标志将其链接到你的 monorepo dev 设置:

¥If you already have a reproduction on your local machine, you can similarly link it to your monorepo dev setup with the --local flag:

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

storybook link 命令在底层依赖于 Yarn 链接。它要求你的本地复制也使用 Yarn 2 或更高版本,如果你已经按照我们的贡献指南使用 storybook sandbox 命令启用它,情况就是这样。如果你尝试链接非 Yarn 2 项目,则该过程将失败。

¥The storybook link command relies on Yarn linking under the hood. It requires your local reproduction to be using Yarn 2 or higher as well, which is the case if you've already enabled it with the storybook sandbox command per our contribution guidelines. The process will fail if you're trying to link a non-Yarn 2 project.

开发模板

¥Developing a template

第一步是向 code/lib/cli/src/sandbox-templates.ts 添加一个条目,它是所有 repro 模板的主列表:

¥The first step is to add an entry to code/lib/cli/src/sandbox-templates.ts, which is the master list of all repro templates:

'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',
    },
  },

添加 inDevelopment 标志直到 PR 合并(你可以快速跟进第二个 PR 以删除该标志),因为它将使开发过程变得更加容易。

¥Add the inDevelopment flag until the PR is merged (you can fast-follow it with a second PR to remove the flag), as it'll make the development process much easier.

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

¥The key cra/default-js consists of two parts:

  • 前缀是用于生成 repro 应用的工具

    ¥The prefix is the tool that was used to generate the repro app

  • 后缀是修改默认安装的选项,例如特定版本或选项

    ¥The suffix is options that modify the default install, e.g. a specific version or options

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

¥The script field is what generates the application environment. The . argument is “the current working directory” which is auto-generated based on the key (e.g. repros/cra/default-js/before-storybook). The {{beforeDir}} key can also be used, which will be replaced by the path of that directory.

其余字段不言自明:

¥The rest of the fields are self-explanatory:

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

¥The skipTasks field exists because some sandboxes might not work properly in specific tasks temporarily, but we might still want to run the other tasks. For instance, a bug was introduced outside of our control, which fails only in the test-runner task.

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

¥The name field should contain a human readable name/description of the template.

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

¥The expected field reflects what framework/renderer/builder we expect sb init to generate. This is useful for assertions while generating sandboxes. If the template is generated with a different expected framework, for instance, it will fail, serving as a way to detect regressions.

运行沙盒

¥Running a sandbox

如果你的模板有 inDevelopment 标志,它将作为沙盒过程的一部分(本地)生成。你可以使用以下命令创建沙箱,其中 <template-key> 由所选模板的 id 替换,例如 cra/default-js

¥If your template has a inDevelopment flag, it will be generated (locally) as part of the sandbox process. You can create the sandbox with the following command, where <template-key> is replaced by the id of the selected template e.g. cra/default-js:

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

带有 inDevelopment 的模板将自动使用 --no-link 标志运行,因为本地模板生成需要它才能工作。

¥Templates with inDevelopment will automatically run with --no-link flag as it is required for the local template generation to work.

PR 合并后,模板将以夜间节奏生成,你可以删除 inDevelopment 标志,沙盒将从我们的模板存储库中提取代码。

¥Once the PR is merged, the template will be generated on a nightly cadence and you can remove the inDevelopment flag and the sandbox will pull the code from our templates repository.

故障排除

¥Troubleshooting

yarn build --all --watch watches everything but is resource-intensive

提前知道要更改哪些包很麻烦,即使在现代机器上,监视它们也非常困难。如果你正在使用足够强大的机器,则可以使用 yarn build --all --watch 而不是 yarn build

¥It's troublesome to know which packages you'll change ahead of time, and watching them can be highly demanding, even on modern machines. If you're working on a powerful enough machine, you can use yarn build --all --watch instead of yarn build.

了解有关为 Storybook 做贡献的更多信息

¥Learn more about contributing to Storybook

  • RFC 流程 用于编写功能请求

    ¥RFC process for authoring feature requests

  • 功能和错误修复的代码

    ¥Code for features and bug fixes

  • 框架 用于开始使用新框架

    ¥Frameworks to get started with a new framework

  • 文档 用于文档改进、拼写错误和澄清

    ¥Documentation for documentation improvements, typos, and clarifications

  • 示例 提供有关新代码片段和示例

    ¥Examples for new snippets and examples