
组件故事格式
简单、通用、面向未来的组件示例

Storybook 是全球最受欢迎的 UI 组件工作室。它支持所有主流视图层(包括 React、Vue、Angular 等)的结构化 UI 开发和测试。
Storybook 5.2 引入了 组件故事格式 (CSF),这是一种基于 ES6 模块的新型故事编写方式。组件故事简洁易读,并且与 Storybook 的内部 API 解耦,因此您可以在任何地方使用它们。
继续阅读以了解更多信息
- 🏆 原因: 主要机遇
- 📄 格式: 是什么 & 为什么它更好
- 🚚 可移植性: Jest 嵌入示例
- 🔀 Codemods: 我们如何轻松升级
- ⚡ 3 分钟安装: 立即开始
- 🔭 下一步?:前进的方向
🏆 为什么需要新格式?
想象一下,如果在 Storybook 中开发组件能够自动解锁使用 Jest 进行测试、导入到 Sketch 设计中、粘贴到 InVision 原型中,以及在 Chromatic 中进行视觉测试的能力。如果您的组件库可以在所有您喜欢的工具中普遍访问,那会怎么样?
在过去的三年里,组件已成为 UI 领域的主导力量。无论您走到哪里,都有面向组件的新工具用于开发、测试、设计和原型制作。

这些工具都围绕着组件和组件示例(也称为*故事*)的**创建**和**消费**。但是,每个工具都有自己的专有格式,因为目前还没有一种简单、平台无关的方式来表达组件示例。
“故事”是组件示例的真实来源
Storybook 的受欢迎程度源于其广泛的开源工具,用于组件开发、测试和文档。这些丰富的功能使其成为 Airbnb、Slack、Squarespace、Lyft、Uber 和 Dropbox 等公司的前端工作流程中不可或缺的一部分。
然而,剥离所有东西后,Storybook 构建于*一个*核心概念之上:故事。
故事是用于在特定状态下渲染组件示例的代码片段。
故事使用已交付给用户的生产代码,这使其成为组件示例最准确的表示。更重要的是,故事以您用来构建应用程序的视图层来表达。
Tom Coleman、Norbert de Langen 和 我 最初的目标是简化在 Storybook 中编写故事。在此过程中,我们意识到创建一个富有表现力、平台无关的格式将允许开发人员在其他工具中使用故事,甚至独立于 Storybook 本身使用。这可以改善所有组件使用者的体验!
📄 组件故事格式
我很高兴推出组件故事格式。如果您使用过早期版本的 Storybook,您可能熟悉“经典”的storiesOfAPI。
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 拥有storiesOfAPI 的所有功能,同时带来了许多额外的优势:
💎 简洁。 编写故事就像从您的故事文件中导出 ES6 函数一样简单,采用一种您熟悉且喜爱的简洁、*标准*格式。
🚚 可移植。 组件故事可以轻松地在任何有 ES6 模块的地方使用,包括您喜欢的测试工具,如 Jest 和 Cypress。
🔥 优化。 组件故事除了您的组件之外,不需要任何库。而且因为它们是 ES6 模块,它们甚至是*可摇树优化*的!
☝️ 声明式。 声明式语法与 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。
即便如此,我们还是希望您升级,因此我们使其变得非常容易。由于storiesOfAPI 中的所有内容在组件故事格式中都有直接的对应项,因此您可以在几秒钟内自动迁移现有故事。
例如,如果您将故事后缀设置为.stories.js,那么转换故事只需在 Storybook CLI 中运行以下命令即可。
npx sb migrate storiesof-to-csf --glob "**/*.stories.js"Storybook 在底层使用了强大的 JSCodeshift 来实现快速轻松的转换。如果从storiesOfAPI 迁移,您还需要 修改对configure的调用。
⚡ 3 分钟安装
立即在 Storybook 5.2 中试用组件故事格式。
npx npm-check-updates '/storybook/' -u && npm install要加载组件故事,Storybook 的configureAPI 会进行一些小改动。这是一个示例.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 之外的其他工具和库中重用他们现有的故事。
📣 在 Medium 或 Twitter 上关注我们,了解该项目如何发展。
💌 如果您正在创建一个可以从 CSF 或任何类型的 Storybook 集成中受益的工具,我们很乐意与您合作。联系我:michael@hichroma.com。
感谢社区
组件故事格式由 Tom Coleman、Norbert de Langen 和 Michael Shilman(我!)开发,并得到了整个 Storybook 社区的测试和反馈。
Storybook 是由 700 多名社区贡献者 的成果,并由顶尖维护者组成的 指导委员会 进行组织。感谢 Open Collective 的慷慨捐赠。
如果 Storybook 让您的 UI 开发工作流程更加轻松,请帮助 Storybook 变得更好。您可以贡献新功能、修复 bug 或改进文档。加入我们的 Discord,在 Open Collective 上支持我们,或者直接在 Github 上参与进来。