T-CREATOR

Storybook リリース運用:Changesets とバージョン別ドキュメントの整備術

Storybook リリース運用:Changesets とバージョン別ドキュメントの整備術

Storybook で UI コンポーネントライブラリを運用する際、バージョン管理とリリースプロセスの整備は避けて通れない課題です。特に複数の開発者が関わるプロジェクトでは、変更履歴の追跡やバージョンごとのドキュメント管理が煩雑になりがちですよね。

本記事では、Changesets を活用した効率的なリリース運用と、バージョン別ドキュメントの整備方法を詳しく解説します。実際の運用フローから具体的な実装例まで、すぐに使える知識をお届けしますので、ぜひ最後までお読みください。

背景

Storybook におけるバージョン管理の重要性

Storybook は UI コンポーネントの開発・ドキュメント化・テストを一元管理できる強力なツールです。しかし、コンポーネントライブラリとして運用する場合、適切なバージョン管理がなければ混乱が生じてしまいます。

特に以下のような状況で課題が顕在化するでしょう。

  • 複数の開発者が同時に異なるコンポーネントを更新する場合
  • Breaking Changes が含まれる変更を明確に伝える必要がある場合
  • 過去のバージョンのドキュメントを参照したい場合

従来のリリース運用の課題

手動でのバージョン管理には多くの労力が必要です。package.json のバージョン番号を更新し、CHANGELOG.md を手書きで記述し、Git タグを作成する…これらの作業は単調でありながらミスが許されません。

また、複数のパッケージを含むモノレポ構成では、依存関係の整合性を保ちながらバージョンを更新する必要があり、さらに複雑さが増します。

下図は従来の手動リリースフローを示しています。

mermaidflowchart TD
  dev["開発者"] -->|コード変更| pr["プルリクエスト作成"]
  pr -->|レビュー| merge["マージ"]
  merge -->|手動| version["package.json<br/>バージョン更新"]
  version -->|手動| changelog["CHANGELOG.md<br/>作成"]
  changelog -->|手動| tag["Git タグ作成"]
  tag -->|手動| publish["npm publish"]
  publish -->|完了| done["リリース完了"]

  style version fill:#ffcccc
  style changelog fill:#ffcccc
  style tag fill:#ffcccc
  style publish fill:#ffcccc

手動作業(赤色部分)が多く、人為的ミスが発生しやすい構造になっています。

Changesets が解決する価値

Changesets は、バージョン管理とリリースプロセスを自動化・標準化するツールです。開発者は変更内容を簡潔に記述するだけで、セマンティックバージョニングに基づいたバージョン更新、CHANGELOG の自動生成、パッケージの公開までを一貫して行えます。

これにより、リリース作業の負担が大幅に軽減され、チーム全体の生産性向上につながるのです。

課題

変更履歴の追跡が困難

手動で CHANGELOG を管理する場合、以下のような問題が発生します。

  • 複数の PR が同時にマージされた際、どの変更をどう記載するか統一が難しい
  • Breaking Changes や新機能、バグ修正の分類が曖昧になる
  • コミットメッセージから変更内容を正確に抽出するのに時間がかかる

結果として、リリース時に「何が変わったのか」を正確に把握できず、利用者への情報提供が不十分になりがちです。

セマンティックバージョニングの適用ミス

セマンティックバージョニング(SemVer)では、バージョン番号を MAJOR.MINOR.PATCH の形式で管理します。

#バージョン変更内容
1MAJORBreaking Changes を含む変更
2MINOR後方互換性のある新機能追加
3PATCH後方互換性のあるバグ修正

しかし、手動管理ではどのバージョンを上げるべきか判断ミスが起こりやすく、利用者に予期せぬ影響を与える可能性があります。

モノレポでの複数パッケージ管理

モノレポ構成では複数のパッケージが相互依存しています。1 つのパッケージを更新した際、依存する他のパッケージも適切にバージョンを更新しなければなりません。

以下の図は、モノレポでの依存関係を示しています。

mermaidflowchart LR
  core["@mylib/core<br/>v1.0.0"] --> button["@mylib/button<br/>v2.0.0"]
  core --> input["@mylib/input<br/>v1.5.0"]
  button --> form["@mylib/form<br/>v3.0.0"]
  input --> form

  style core fill:#e3f2fd
  style button fill:#e3f2fd
  style input fill:#e3f2fd
  style form fill:#e3f2fd

@mylib​/​core を更新すると、それに依存する buttoninputform すべてのバージョン管理が必要になります。手動では依存関係の追跡が極めて困難です。

バージョン別ドキュメントの欠如

Storybook で公開したドキュメントは、通常は最新バージョンのみが表示されます。しかし、古いバージョンを使用している利用者にとっては、過去のドキュメントにアクセスできないと困るでしょう。

特に Enterprise 向けのライブラリでは、バージョンアップが慎重に行われるため、複数バージョンのドキュメントを並行して提供する必要があります。

解決策

Changesets の導入

Changesets を使えば、変更内容の記録からバージョン更新、CHANGELOG 生成、パッケージ公開まで、一連のリリースフローを自動化できます。

Changesets を導入すると、開発者は PR 作成時に変更の種類(major / minor / patch)と説明文を記載した「changeset ファイル」を追加します。リリース時にはこれらを集約して、自動的にバージョンを決定し CHANGELOG を生成してくれるのです。

以下の図は、Changesets を使った自動化されたリリースフローです。

mermaidflowchart TD
  dev["開発者"] -->|コード変更| pr["プルリクエスト作成"]
  pr -->|yarn changeset| cs["changeset ファイル追加"]
  cs -->|レビュー| merge["マージ"]
  merge -->|自動| bot["Changesets Bot"]
  bot -->|Version PR 作成| vpr["バージョン更新 PR"]
  vpr -->|マージ| release["自動リリース"]
  release -->|完了| done["リリース完了"]

  style bot fill:#c8e6c9
  style vpr fill:#c8e6c9
  style release fill:#c8e6c9

緑色の部分が自動化され、人為的ミスを防ぎつつ作業効率が向上します。

Changesets の基本設定

まずは Changesets をプロジェクトにインストールしましょう。

bashyarn add -D @changesets/cli

インストール後、初期化を実行します。

bashyarn changeset init

これにより、.changeset ディレクトリと config.json が生成されます。

設定ファイルの内容を確認してみましょう。

json{
  "$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json",
  "changelog": "@changesets/cli/changelog",
  "commit": false,
  "fixed": [],
  "linked": [],
  "access": "restricted",
  "baseBranch": "main",
  "updateInternalDependencies": "patch",
  "ignore": []
}

各項目の意味を表で整理します。

#項目説明
1changelogCHANGELOG 生成に使用するプラグイン
2commitchangeset 追加時に自動コミットするか
3accessパッケージの公開範囲(public/restricted)
4baseBranchリリース対象のベースブランチ
5updateInternalDependencies内部依存の更新ルール

必要に応じてこれらの設定を調整してください。

Changeset ファイルの追加

開発者がコンポーネントを変更したら、以下のコマンドで changeset ファイルを追加します。

bashyarn changeset

対話形式で以下の質問に答えていきます。

  1. どのパッケージを変更したか(複数選択可)
  2. バージョンの種類(major / minor / patch)
  3. 変更内容の説明

これにより、.changeset ディレクトリ内にランダムな名前の Markdown ファイルが生成されます。

markdown---
'@mylib/button': minor
---

ボタンコンポーネントに loading 状態を追加しました

このファイルを Git にコミットし、PR に含めます。

バージョン更新の実行

複数の changeset ファイルがマージされたら、バージョン更新を実行します。

bashyarn changeset version

このコマンドは以下の処理を自動で行います。

  • すべての changeset ファイルを読み込む
  • セマンティックバージョニングに基づいてバージョンを決定
  • package.json のバージョンを更新
  • CHANGELOG.md を生成または更新
  • changeset ファイルを削除

生成された CHANGELOG.md の例を見てみましょう。

markdown# @mylib/button

# 2.1.0

## Minor Changes

- a1b2c3d: ボタンコンポーネントに loading 状態を追加しました

## Patch Changes

- Updated dependencies [a1b2c3d]
  - @mylib/core@1.1.0

変更の種類ごとに整理され、依存関係の更新も自動的に記録されています。

GitHub Actions での自動化

CI/CD パイプラインに Changesets を組み込むことで、さらに効率化できます。

GitHub Actions のワークフローファイルを作成しましょう。

yamlname: Release

on:
  push:
    branches:
      - main

concurrency: ${{ github.workflow }}-${{ github.ref }}

これは main ブランチへのプッシュ時にワークフローを実行する設定です。

次に、ジョブの定義を追加します。

yamljobs:
  release:
    name: Release
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v3

リポジトリをチェックアウトする基本ステップです。

Node.js と Yarn のセットアップを行います。

yaml- name: Setup Node.js
  uses: actions/setup-node@v3
  with:
    node-version: 18

- name: Install Dependencies
  run: yarn install --frozen-lockfile

依存関係をインストールし、環境を整えます。

Changesets のアクションを実行します。

yaml- name: Create Release Pull Request or Publish
  uses: changesets/action@v1
  with:
    publish: yarn release
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

このステップでは、以下の動作を自動で行います。

  • changeset ファイルが存在する場合:バージョン更新 PR を自動作成
  • バージョン更新 PR がマージされた場合:パッケージを npm に公開

yarn release コマンドは package.json に定義しておきましょう。

json{
  "scripts": {
    "release": "yarn build && changeset publish"
  }
}

ビルドを実行した後、パッケージを公開する流れです。

バージョン別ドキュメントの整備

Storybook で複数バージョンのドキュメントを提供するには、storybook-deployer や Chromatic などのツールを活用します。

ここでは、GitHub Pages を使った方法を紹介しましょう。

まず、バージョンごとに Storybook をビルドし、ディレクトリ構造を整理します。

bashyarn build-storybook -o docs/v2.1.0
yarn build-storybook -o docs/v2.0.0
yarn build-storybook -o docs/v1.5.0

各バージョンのビルド成果物を docs ディレクトリ内に配置します。

次に、バージョン選択用のランディングページを作成しましょう。

html<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <title>Storybook バージョン一覧</title>
  </head>
  <body>
    <h1>コンポーネントライブラリ ドキュメント</h1>
    <ul>
      <li><a href="v2.1.0/">v2.1.0(最新)</a></li>
      <li><a href="v2.0.0/">v2.0.0</a></li>
      <li><a href="v1.5.0/">v1.5.0</a></li>
    </ul>
  </body>
</html>

このファイルを docs​/​index.html として保存します。

GitHub Actions でデプロイを自動化する設定も追加しましょう。

yaml- name: Deploy to GitHub Pages
  uses: peaceiris/actions-gh-pages@v3
  with:
    github_token: ${{ secrets.GITHUB_TOKEN }}
    publish_dir: ./docs

これにより、リリースごとに新しいバージョンのドキュメントが自動的に公開されます。

具体例

実際の運用フロー

実際のプロジェクトでの運用例を見ていきましょう。

ステップ 1:新機能の開発

開発者が新しいコンポーネント機能を追加します。例として、Button コンポーネントに variant="outlined" を追加するとします。

コンポーネントファイルを編集します。

typescript// packages/button/src/Button.tsx
import React from 'react';

interface ButtonProps {
  children: React.ReactNode;
  variant?: 'solid' | 'outlined';
  onClick?: () => void;
}

型定義を追加し、variant プロパティを受け取れるようにします。

コンポーネントのロジックを実装します。

typescriptexport const Button: React.FC<ButtonProps> = ({
  children,
  variant = 'solid',
  onClick,
}) => {
  const className =
    variant === 'outlined'
      ? 'button button--outlined'
      : 'button button--solid';

  return (
    <button className={className} onClick={onClick}>
      {children}
    </button>
  );
};

variant に応じてクラス名を切り替え、スタイルを適用する仕組みです。

Storybook のストーリーも追加しましょう。

typescript// packages/button/src/Button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';

const meta: Meta<typeof Button> = {
  title: 'Components/Button',
  component: Button,
};

export default meta;
type Story = StoryObj<typeof Button>;

メタデータを定義し、コンポーネントを Storybook に登録します。

各 variant のストーリーを作成します。

typescriptexport const Solid: Story = {
  args: {
    children: 'Solid Button',
    variant: 'solid',
  },
};

export const Outlined: Story = {
  args: {
    children: 'Outlined Button',
    variant: 'outlined',
  },
};

これで Storybook 上で両方のバリエーションを確認できるようになります。

ステップ 2:Changeset の追加

開発が完了したら、changeset ファイルを追加します。

bashyarn changeset

対話的に以下を選択・入力します。

  • パッケージ:@mylib​/​button
  • バージョンタイプ:minor(新機能追加のため)
  • 説明:Button コンポーネントに outlined variant を追加

生成された changeset ファイルの内容を確認しましょう。

markdown---
'@mylib/button': minor
---

Button コンポーネントに outlined variant を追加

このファイルを含めて PR を作成します。

ステップ 3:PR のレビューとマージ

PR がレビューされ、承認されたらマージします。

マージ後、GitHub Actions が自動的に実行され、Changesets Bot が「Version Packages」という PR を作成します。

この PR には以下の変更が含まれています。

  • packages​/​button​/​package.json のバージョンが 2.0.02.1.0 に更新
  • packages​/​button​/​CHANGELOG.md に新しいエントリが追加
  • .changeset 内のファイルが削除

Version Packages PR の CHANGELOG 更新内容を見てみましょう。

markdown# @mylib/button

# 2.1.0

## Minor Changes

- 3f4a5b6: Button コンポーネントに outlined variant を追加

# 2.0.0

## Major Changes

- 1a2b3c4: Button API を大幅に変更

過去のバージョン履歴も保持されており、変更の追跡が容易です。

ステップ 4:リリースの実行

Version Packages PR をマージすると、再び GitHub Actions が起動し、以下を実行します。

  1. パッケージをビルド
  2. npm にパッケージを公開
  3. Git タグを作成
  4. GitHub Releases を作成

すべて自動化されているため、手動作業は不要です。

ステップ 5:ドキュメントの更新

新バージョンのドキュメントを生成し、公開します。

bashyarn build-storybook -o docs/v2.1.0

ビルドされた Storybook を新しいバージョンディレクトリに配置します。

ランディングページも更新しましょう。

html<ul>
  <li><a href="v2.1.0/">v2.1.0(最新)</a></li>
  <li><a href="v2.0.0/">v2.0.0</a></li>
  <li><a href="v1.5.0/">v1.5.0</a></li>
</ul>

最新バージョンのリンクを先頭に追加します。

GitHub Pages へデプロイすれば、複数バージョンのドキュメントが並行して公開されます。

モノレポでの実践例

モノレポ構成では、複数パッケージの依存関係を適切に管理する必要があります。

以下のようなパッケージ構成を想定しましょう。

csspackages/
├── core/          # 基本ユーティリティ
├── button/        # core に依存
├── input/         # core に依存
└── form/          # buttoninput に依存

依存関係を図で示します。

mermaidflowchart TB
  core["@mylib/core"]
  button["@mylib/button"]
  input["@mylib/input"]
  form["@mylib/form"]

  core --> button
  core --> input
  button --> form
  input --> form

core を更新すると、依存するすべてのパッケージに影響します。

@mylib​/​core に新しいユーティリティ関数を追加したとします。

typescript// packages/core/src/utils.ts

/**
 * 文字列を capitalize する
 */
export function capitalize(str: string): string {
  return str.charAt(0).toUpperCase() + str.slice(1);
}

シンプルなユーティリティ関数です。

changeset を追加します。

bashyarn changeset

選択内容:

  • パッケージ:@mylib​/​core
  • バージョンタイプ:minor
  • 説明:capitalize 関数を追加

@mylib​/​button でこの関数を使用するよう更新します。

typescript// packages/button/src/Button.tsx
import { capitalize } from '@mylib/core';

export const Button: React.FC<ButtonProps> = ({
  children,
  ...props
}) => {
  const label =
    typeof children === 'string'
      ? capitalize(children)
      : children;

  return <button {...props}>{label}</button>;
};

core の新機能を活用しています。

button でも changeset を追加しましょう。

bashyarn changeset

選択内容:

  • パッケージ:@mylib​/​button
  • バージョンタイプ:patch
  • 説明:capitalize 関数を使用してボタンラベルを処理

これで 2 つの changeset ファイルが作成されました。

バージョン更新を実行します。

bashyarn changeset version

Changesets は依存関係を解析し、以下のように更新します。

#パッケージ旧バージョン新バージョン理由
1@mylib/core1.2.01.3.0minor 変更
2@mylib/button2.1.02.1.1patch 変更
3@mylib/input1.5.01.5.1core 依存の patch 更新
4@mylib/form3.0.03.0.1button/input 依存の patch 更新

直接変更していない inputform も、内部依存の更新ルールに従って自動的にバージョンアップされます。

CHANGELOG の活用

生成された CHANGELOG は、利用者にとって重要な情報源です。

@mylib​/​core の CHANGELOG を見てみましょう。

markdown# @mylib/core

# 1.3.0

## Minor Changes

- 7c8d9e0: capitalize 関数を追加

# 1.2.0

## Minor Changes

- 4f5g6h7: formatDate 関数を追加

## Patch Changes

- 8i9j0k1: 型定義のエクスポートを修正

バージョンごとに変更内容が整理され、検索性も高くなっています。

@mylib​/​button の CHANGELOG も確認しましょう。

markdown# @mylib/button

# 2.1.1

## Patch Changes

- a1b2c3d: capitalize 関数を使用してボタンラベルを処理
- Updated dependencies [7c8d9e0]
  - @mylib/core@1.3.0

# 2.1.0

## Minor Changes

- 3f4a5b6: Button コンポーネントに outlined variant を追加

依存パッケージの更新情報も含まれており、全体像が把握しやすいですね。

これらの CHANGELOG は npm パッケージページや GitHub Releases にも自動的に反映されます。

まとめ

Changesets を活用することで、Storybook のリリース運用を大幅に効率化できます。手動でのバージョン管理や CHANGELOG 作成から解放され、開発者は本質的な開発作業に集中できるようになるでしょう。

本記事で紹介した内容をまとめます。

  • Changesets の導入により、バージョン管理と CHANGELOG 生成を自動化
  • セマンティックバージョニングを適切に適用し、利用者に明確な情報を提供
  • モノレポ構成でも依存関係を自動追跡し、一貫性のあるリリースを実現
  • GitHub Actions と連携して、CI/CD パイプラインに組み込み
  • バージョン別ドキュメントを整備し、複数バージョンのサポートを実現

これらの仕組みを導入することで、チーム全体の生産性が向上し、より高品質なコンポーネントライブラリを提供できます。ぜひあなたのプロジェクトでも試してみてください。

関連リンク