Storybook

Storybook 是一种流行的在隔离环境中构建 UI 组件的方式。通过将 Storybook 放入你的 Turborepo 中,你可以轻松地与你的应用程序一起开发你的设计系统。

快速开始

如果你更喜欢使用模板,本指南将引导你了解如何在 Vercel 上构建这个 Storybook/Turborepo 模板

终端
pnpm dlx create-turbo@latest -e design-system

指南

创建 monorepo

如果你没有现有项目,请使用 create-turbo 创建一个新的 monorepo

终端
pnpm dlx create-turbo@latest

为应用创建目录

你需要一个用于 Storybook 应用的目录

终端
mkdir apps/storybook
cd apps/storybook

添加 Storybook 应用

apps/storybook 目录中,初始化一个新的 Storybook 应用

终端
pnpm create storybook@latest

按照提示创建一个应用。在本指南的其余部分,我们将假设使用 React 和 TypeScript。

须知: 

在完成 Storybook 的入门引导后,你可以卸载入门引导插件

将你的 UI 工具包添加到 Storybook

现在,将你的 UI 包安装到 Storybook 中。

终端
pnpm install @repo/ui --filter=storybook

为你的 Button 组件设置一个 story

删除 Storybook 脚手架工具在 src/stories 中创建的 stories 和组件。你将创建自己的。

例如,这是来自 @repo/ui/buttonButton 组件的一个 story。

./apps/storybook/src/stories/Button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from '@repo/ui/button';
 
const meta = {
  title: 'Example/Button',
  component: Button,
  tags: ['autodocs'],
} satisfies Meta<typeof Button>;
 
export default meta;
type Story = StoryObj<typeof meta>;
 
export const Primary: Story = {
  args: {
    appName: 'Button',
    children: 'I am a primary button.',
  },
};

将脚本与你的任务对齐

最后,将新的 Storybook 应用集成到你的 Turborepo 中

apps/storybook/package.json
{
  "scripts": {
    "dev": "storybook dev -p 6006",
    "build": "storybook build"
  }
}

这些脚本现在将与你的 turbo.json 中的 turbo devturbo build 任务一起运行。

为了确保在你运行 build 时文件输出被缓存,将 storybook-static 添加到你的 turbo.json build 任务的 outputs 中

Turborepo logo
turbo.json
{
  "tasks": {
    "build": {
      "outputs": [
        ".next/**",
        "!.next/cache/**"
+       "storybook-static/**"
      ]
    }
  }
}

将 Storybook 构建输出添加到 .gitignore

确保 Storybook 的构建输出不提交到源代码控制

.gitignore
+ storybook-static

验证你的配置

运行 turbo build 以与你的其余应用程序一起构建 Storybook 应用。

你也可以再次运行 turbo build 以查看你的构建的缓存命中情况。

更多提示

共同放置 stories

如果你更喜欢将你的 stories 与它们的源代码共同放置(而不是放在 Storybook 应用中),你需要一些额外的配置。

重新配置 Storybook 源

.storybook/main.ts 中,将 config 中的 stories 路径更改为你想要捕获的目录。例如,如果你想在 UI 包中编写 stories

./apps/storybook/.storybook/main.ts
 
const config = {
  stories: [
-   "../src/**/*.mdx",
-   "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
+   "../../../packages/ui/src/**/*.stories.@(js|jsx|mjs|ts|tsx)",
};

将 story 文件移动到 UI 包

按照上面的指南,将 ./apps/storybook/src/stories/Button.stories.tsx 文件移动到 ./packages/ui/src/Button.stories.tsx

更新组件导入,以便它们引用现在共同放置的模块。例如,在 story 的导入中

./packages/ui/src/Button.stories.tsx
- import { Button } from "@repo/ui/button";
+ import { Button } from "./button";

须知: 

你可能还需要根据你的更改和用法更新绝对导入

你还需要安装编写 stories 所需的任何 Storybook 包。例如,从上面移动 story 将需要你将 @storybook/react 安装到你的 @repo/ui 包中。

终端
pnpm install @storybook/react --filter=@repo/ui --save-dev

配置缓存

因为 stories 现在在 UI 包中,所以对这些 stories 的更改可能会导致任何依赖于你的 UI 包的构建的缓存未命中。但是,更改 story 并不意味着你的生产应用程序应该错过缓存。

为了防止这种情况,请从根 turbo.jsonbuild 任务的 inputs 中排除 stories。你还需要创建一个 build:storybook 任务,你稍后会需要它

Turborepo logo
./turbo.json
{
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "inputs": ["$TURBO_DEFAULT$", "!**/*.stories.{tsx,jsx,mdx}"],
      "outputs": [".next/**", "!.next/cache/**"]
    },
    "build:storybook": {} 
  }
}

此外,在 storybook 应用中创建一个包配置,以便在构建 Storybook 应用时考虑到 stories,特别是

Turborepo logo
./apps/storybook/turbo.json
{
  "extends": ["//"],
  "tasks": {
    "build:storybook": {
      "dependsOn": ["^build:storybook"],
      "outputs": ["storybook-static/**"]
    }
  }
}

须知: 

如果你正在使用Compiled Package 模式,你可能还需要将 ^build 添加到你的 dependsOn 中。

重命名 build 脚本

最后,确保你用于构建 Storybook 的脚本通过将其重命名为任务名称来使用我们刚刚编写的配置

apps/storybook/package.json
{
  "scripts": {
    "dev": "storybook dev -p 6006",
    "build:storybook": "storybook build"
  }
}

曾经是 "build" 的脚本现在是 "build:storybook",以确保 stories 包含在用于缓存的哈希中。

验证你的配置

为了确保你的设置正确

  1. 运行 turbo build:storybook build。你应该看到缓存未命中。
  2. 再次运行 turbo build:storybook build。你应该看到所有缓存命中。
  3. 在你的 @repo/ui 包中对一个 story 进行代码更改。
  4. 再次运行 turbo build:storybook build。你应该只看到 Storybook 应用的缓存未命中。所有其他应用都应该命中缓存。

添加 CSS

如果你的 UI 包导出了自己的 CSS,你需要在 Storybook 应用的渲染器中添加它,类似于你将它添加到你的应用程序的方式。《Storybook 文档》建议你将其添加到 .storybook/preview.ts 文件中。