Turborepo

Storybook

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

快速入门

如果您更喜欢使用模板,本指南将逐步介绍如何在 Vercel 上构建此 Storybook/Turborepo 模板

终端
npx create-turbo@latest -e design-system

指南

创建一个 monorepo

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

终端
npx create-turbo@latest

为应用程序创建一个目录

您需要一个用于 Storybook 应用程序的目录

终端
mkdir apps/storybook
cd apps/storybook

添加 Storybook 应用程序

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

终端
npx storybook@latest init

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

须知

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

将您的 UI 工具包添加到 Storybook

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

终端
npm install @repo/ui --workspace=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 构建任务的输出中

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 包中。

终端
npm install @storybook/react --workspace=@repo/ui --save-dev

配置缓存

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

为了防止这种情况,请在根 turbo.json 中将 stories 从 build 任务的输入中排除。您还需要创建一个 build:storybook 任务,您稍后会用到

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

此外,在 storybook 应用程序中创建一个包配置,以便 stories 在构建 Storybook 应用程序时被考虑在内,尤其是

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

须知

如果您使用的是编译包模式,您可能还需要将 ^build 添加到您的 dependsOn

重命名构建脚本

最后,请确保您的构建 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 文件中。

小时

节省的总计算时间
开始使用
远程缓存 →

本页内容