返回博客

组件故事格式

简单、可移植、面向未来的组件示例

loading
Michael Shilman
@mshilman
最后更新

Storybook 是世界上最流行的 UI 组件工作台。它为包括 React、Vue、Angular 和更多主流视图层在内的所有框架,实现了结构化的 UI 开发和测试。

Storybook 5.2 引入了组件故事格式 (CSF),这是一种基于 ES6 模块编写 Story 的新方法。组件故事简洁、易读,并且与 Storybook 内部 API 解耦,因此你可以在任何地方使用它们。

继续阅读以了解更多

  • 🏆 为什么:巨大的机遇
  • 📄 格式:它是什么以及为什么更好
  • 🚚 可移植性:Jest 嵌入示例
  • 🔀 代码转换:我们如何让升级变得容易
  • 3 分钟安装:立即开始
  • 🔭 下一步是什么?:前进的方向

🏆 为什么要使用新格式?

想象一下,如果在 Storybook 中开发组件能够自动解锁以下能力:使用 Jest 进行测试,将其导入 Sketch 设计稿,粘贴到 InVision 原型中,并在 Chromatic 中进行可视化测试。如果你的组件库可以在你所有喜欢的工具中通用访问,那会怎么样?

在过去的三年中,组件已经崛起并主导了 UI 领域。放眼望去,到处都是面向组件的开发、测试、设计和原型设计工具。

这些工具参与组件和组件示例(又名“故事”)的创建消费。但是,每个工具都有自己的专有格式,因为一种简单、平台无关的方式来表达组件示例尚不存在。

“故事”是组件示例的真理来源

Storybook 的流行源于其用于组件开发、测试和文档的广泛开源工具。这些丰富的功能使其成为 Airbnb、Slack、Squarespace、Lyft、Uber 和 Dropbox 等巨头前端工作流程中不可或缺的一部分。

然而,如果你剥开一切,Storybook 是建立在一个核心结构之上的:故事

故事是一段代码片段,用于渲染组件在特定状态下的示例。

故事使用交付给用户的生产代码,这使其成为组件示例最准确的表示。更重要的是,故事是在你用于构建应用程序的视图层中表达的。

Tom ColemanNorbert de Langen 最初的目标是简化在 Storybook 中编写故事的过程。在此过程中,我们意识到创建一种富有表现力、平台无关的格式将允许开发人员在其他工具中使用故事,甚至独立于 Storybook 本身。这可以改善每个使用组件的人的体验!

📄 组件故事格式

我很高兴介绍组件故事格式。如果你使用过早期版本的 Storybook,你可能熟悉“经典”的 storiesOf API。

storiesOf('atoms/Button', module)
  .add('text', () => <Button>Hello</Button>)
  .add('emoji', () => <Button>😀😎👍💯</Button>);

这个经过验证的 API 可以完成工作。但是,在帮助数万名开发人员捕获、记录和测试关键组件状态之后,我们想出了一个更好的方法。

export default { title: 'atoms/Button' };

export const text = () => <Button>Hello</Button>;
export const emoji = () => <Button>😀😎👍💯</Button>;

CSF 拥有 storiesOf API 的所有功能,但带来了许多额外的优势。

💎 简单。编写故事就像从你的故事文件中导出 ES6 函数一样简单,采用你熟悉和喜爱的简洁、标准格式。

🚚 可移植。组件故事可以轻松地在任何 ES6 模块存在的地方使用,包括你最喜欢的测试工具,如 Jest 和 Cypress。

🔥 优化。组件故事除了你的组件之外,不需要任何库。而且因为它们是 ES6 模块,所以它们甚至可以进行 tree-shaking

☝️ 声明式。声明式语法与更高级别的格式(如 MDX)同构,从而实现干净、可验证的转换。

👾 面向未来。组件故事隐藏了 Storybook 的底层 API,使维护者可以灵活地改进 Storybook 而不会破坏任何约定。

🚚 故事可移植性

组件故事不依赖于 Storybook,因此使用它们就像导入 ES6 模块一样简单。考虑一下我们如何使用 Jest 和 react-testing-library 测试交互性。

这是一个用于有状态 Counter 组件的 CSF 文件,该组件在每次点击时增加其计数:

export default { title: 'Counter' };

export const enabled = () => (
  <Counter text="Enabled" />
);

export const disabled = () => (
  <Counter disabled text="Disabled" />
);

这是我们如何在交互式测试中使用它的方法:

import { render, fireEvent } from '@testing-library/react';
import { enabled, disabled } from './Button.stories';

describe('counter interactivity', () => {

  it('should increment when enabled', () => {
    const comp = render(enabled());
    fireEvent.click(comp.getByText('Enabled: 0'));
    expect(comp.getByText('Enabled: 1')).toBeTruthy();
  });
  
  it('should do nothing when disabled', () => {
    const comp = render(enabled());
    fireEvent.click(comp.getByText('Disabled: 0'));
    expect(comp.getByText('Disabled: 0')).toBeTruthy();
  });
  
});

使用组件故事格式,这种集成简单而自然。使用 storiesOf 实现相同的结果将需要对你的代码进行重大重组。

🔀 便捷的代码迁移

那么你现有的故事库呢?不必担心。由于我们现有的所有用户群都依赖于 Storybook 的经典 API,我们将在可预见的未来继续支持 storiesOf

话虽如此,我们希望你升级,因此我们使其变得非常容易。由于 storiesOf API 中的所有内容在组件故事格式中都有直接的等价物,因此你可以在几秒钟内自动迁移你现有的故事。

例如,如果你在你的故事后面加上 `.stories.js` 后缀,那么转换你的故事就像在 Storybook CLI 中运行以下命令一样简单:

npx sb migrate storiesof-to-csf --glob "**/*.stories.js"

Storybook 在底层使用了强大的 JSCodeshift 来使这种转换快速而简单。如果你是从 storiesOf API 迁移过来的,你还需要修改你对 configure 的调用。

⚡ 3 分钟安装

立即在 Storybook 5.2 中试用组件故事格式

npx npm-check-updates '/storybook/' -u && npm install

为了加载组件故事,Storybook 的 configure API 进行了一些小的改动。这是一个示例 `.storybook/config.js`:

import { configure } from ‘@storybook/react’;

configure(require.context(‘../src/’, true, /\.stories\.js$/), module);

最后,你可以添加一个新的故事来验证它是否工作,然后在你的故事库上运行自动化迁移(见上文)。迁移会覆盖你的文件,因此请确保你的故事在版本控制中。

或者,如果你想在一个新项目中尝试它,Storybook 的默认设置现在默认使用组件故事。

cd my-react-vue-angular-project
npx -p @storybook/cli@next sb init

就这样搞定了!🎉

🔭 下一步是什么?

组件故事格式是 Storybook 向前迈出的基础性一步,它带来了立竿见影的好处,包括简洁性、可移植性和可优化性。

该格式的长期利益将更加巨大。一种开放、可移植且基于标准的格式使整个组件设计和开发工具生态系统能够为了用户的利益协同工作。

作为最流行的组件浏览器,Storybook 定位良好,可以推广通用标准。超过 20,000 个 GitHub 仓库依赖于 Storybook(据我们所知),世界各地最大的公司都在所有主流前端视图层中使用它。它在 NPM 上的每月安装量超过 400 万次。

Storybook 用户已经在过渡到 CSF,以便他们可以在 Storybook 之外的其他工具和库中重用他们现有的故事。

📣 在 MediumTwitter 上关注我们,了解该项目的发展。

💌 如果你正在创建一个可以从 CSF 或任何类型的 Storybook 集成中受益的工具,我们很乐意合作。联系我:michael@hichroma.com

感谢社区

组件故事格式由 Tom ColemanNorbert de LangenMichael Shilman(我!)开发,并得到了整个 Storybook 社区的测试和反馈。

Storybook 是 700 多名社区贡献者的成果,并由顶级维护者的指导委员会组织。还要感谢在 Open Collective 上的慷慨捐款。

如果 Storybook 使你的 UI 开发工作流程更轻松,请帮助 Storybook 变得更好。你可以贡献新功能、修复错误或改进文档。在 Discord 上加入我们,在 Open Collective 上支持我们,或者直接参与 Github

加入 Storybook 邮件列表

获取最新的新闻、更新和发布

6,730位开发者和计数

我们正在招聘!

加入 Storybook 和 Chromatic 背后的团队。构建被数十万开发人员在生产环境中使用的工具。远程优先。

查看职位

热门文章

Storybook 文档页

漂亮的文档,即刻呈现
loading
Michael Shilman

Storybook 5.2

世界一流的设计系统基础设施
loading
Michael Shilman

Storybook 5.1

React Native • 可访问性 • Context • 预设 • 文档更新
loading
Michael Shilman
加入社区
6,730位开发者和计数
为什么为什么选择 Storybook组件驱动的 UI
文档指南教程更新日志遥测
社区插件参与其中博客
案例展示探索项目组件术语表
开源软件
Storybook - Storybook 中文

特别感谢 Netlify CircleCI