Storybook

Storybook은 격리된 환경에서 UI 컴포넌트를 빌드하는 인기 있는 방법입니다. Storybook을 Turborepo에 넣으면 애플리케이션과 함께 디자인 시스템을 쉽게 개발할 수 있습니다.

빠른 시작

템플릿을 사용하려는 경우, 이 가이드는 Vercel에서 이 Storybook/Turborepo 템플릿을 빌드하는 방법을 안내합니다.

Terminal
pnpm dlx create-turbo@latest -e design-system

가이드

monorepo 만들기

기존 프로젝트가 없는 경우, create-turbo를 사용하여 새 monorepo를 만듭니다:

Terminal
pnpm dlx create-turbo@latest

앱용 디렉터리 생성

Storybook 애플리케이션용 디렉터리가 필요합니다:

Terminal
mkdir apps/storybook
cd apps/storybook

Storybook 애플리케이션 추가

apps/storybook 디렉터리에서 새 Storybook 애플리케이션을 초기화합니다:

Terminal
pnpm create storybook@latest

프롬프트에 따라 애플리케이션을 만듭니다. 이 가이드의 나머지 부분에서는 React 및 TypeScript를 사용한다고 가정합니다.

Good to know: 

Storybook의 온보딩을 완료한 후 온보딩 애드온을 제거할 수 있습니다.

Storybook에 UI 키트 추가

이제 UI 패키지를 Storybook에 설치합니다.

Terminal
pnpm add @repo/ui --filter=storybook

Button 컴포넌트에 대한 스토리 설정

Storybook 스캐폴딩 도구로 생성된 src/stories에서 스토리 및 컴포넌트를 삭제합니다. 직접 만들 것입니다.

예를 들어, @repo/ui/buttonButton 컴포넌트에 대한 스토리는 다음과 같습니다.

./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.jsonturbo devturbo build 작업과 함께 실행됩니다.

build를 실행할 때 파일 출력이 캐시되도록 하려면 turbo.json 빌드 작업의 출력에 storybook-static을 추가합니다:

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

Storybook 빌드 출력을 .gitignore에 추가

Storybook의 빌드 출력이 소스 제어에 커밋되지 않도록 합니다

.gitignore
+ storybook-static

구성 확인

turbo build를 실행하여 Storybook 애플리케이션과 나머지 애플리케이션을 함께 빌드합니다.

turbo build를 다시 실행하여 빌드에 대한 캐시 적중을 볼 수도 있습니다.

더 많은 팁

스토리 같은 위치 배치

스토리를 소스 코드와 함께 배치하려는 경우(Storybook 애플리케이션에 있는 대신), 몇 가지 추가 구성이 필요합니다.

Re-configure Storybook sources

In .storybook/main.ts, change the stories paths in config to the directories you'd like to capture. For instance, if you'd like to write stories in the UI package:

./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)",
};

Move story files to the UI package

Following along with the guide above, move the ./apps/storybook/src/stories/Button.stories.tsx file to ./packages/ui/src/Button.stories.tsx.

Update components imports so that they reference the now co-located modules. For instance, in the story's imports:

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

Good to know: 

You may also need to update absolute imports according to your changes and usage.

You'll also need to install any Storybook packages required for writing stories. For example, moving the story from above would require that you install @storybook/react into your @repo/ui package.

Terminal
pnpm add @storybook/react --filter=@repo/ui --save-dev

Configure caching

Because stories are now in the UI package, changes to those stories can cause cache misses for any builds that depend on your UI package. However, changing a story doesn't mean your production applications should miss cache.

To prevent this, exclude stories from the inputs to your build task in your root turbo.json. You'll also need to create a build:storybook task, which you'll need in a moment:

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

Additionally, create a Package Configuration in the storybook application so stories are accounted for in building the Storybook application, specifically:

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

Good to know: 

If you are using the Compiled Package pattern, you may also need to add ^build to your dependsOn.

Rename the build script

Last, make sure your script to build Storybook uses the configuration we just wrote by renaming it to the name of the task:

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

The script that was once "build" is now "build:storybook" to ensure the stories are included in hashes for caching.

Verify your configuration

To ensure your setup is correct:

  1. Run turbo build:storybook build. You should see cache misses.
  2. Run turbo build:storybook build again. You should see all cache hits.
  3. Make a code change to a story in your @repo/ui package.
  4. Run turbo build:storybook build again. You should only see a cache miss for the Storybook application. All others should hit cache.

Adding CSS

If your UI package exports its own CSS, you'll need to add it to the renders in the Storybook app, similar to how you would add it to your applications. The Storybook documentation recommends you add it to the .storybook/preview.ts file.