はじめに
Storybookがどのようなものか知りたかったので触ってみました。コンポーネントの見た目の確認が楽なので、UIのボトムアップな開発には有益そうと感じました。
想定読者はReact何となくわかるくらいの方です*1。
Storybook
Storybookとはコンポーネントの開発をサポートするツールです。コンポーネントごとに見た目の確認ができます。ReactやReact Native, Vue, Angular and Svelteなどに対応しています。
The Storybook Story
2016年の4月にKadiraというスリランカのスタートアップにより1.0がリリースされました。その後一度メンテがされなった期間を経てコミュニティ主導に復活したという面白いストーリーがあるようです(The Storybook Story)。
導入
npx -p @storybook/cli sb init
で必要なパッケージやデフォルトの設定がされてStoryboxがアプリケーションに追加されます。yarn storybook
で起動します。見た目は↓のような感じです。
コンポーネント
コンポーネントは再利用できるGUIの部品です。Storybookではコンポーネントを作ったそばから見た目が確認できます。見た目の確認はVisual Testingというそうです*2。
コード例
例としてタスクリストのタスクのコードを載せます。
アプリケーション用コード
src/components/Task.js
import React from 'react'; export default function Task({ task: { id, title, state }, onArchiveTask, onPinTask }) { return ( <div className="list-item"> <input type="text" value={title} readOnly={true} /> </div> ); }
Storybook用コード
Taskコンポーネントを読み込み、別々のモックデータを与えてexportしています。ここではデフォルト状態とピン状態とアーカイブ状態のTaskコンポーネントをexportしています。これらはStoryと呼ばれます。この仕組によりStorybookで状態が違うコンポーネントの見た目が確認ができます。
src/components/Task.stories.js
import React from 'react'; import { action } from '@storybook/addon-actions'; import Task from './Task'; export default { component: Task, title: 'Task', excludeStories: /.*Data$/, }; export const taskData = { id: '1', title: 'Test Task', state: 'TASK_INBOX', updatedAt: new Date(2018, 0, 1, 9, 0), }; export const actionsData = { onPinTask: action('onPinTask'), onArchiveTask: action('onArchiveTask'), }; export const Default = () => <Task task={{ ...taskData }} {...actionsData} />; export const Pinned = () => <Task task={{ ...taskData, state: 'TASK_PINNED' }} {...actionsData} />; export const Archived = () => ( <Task task={{ ...taskData, state: 'TASK_ARCHIVED' }} {...actionsData} /> );
Storybook
Storybookでみると、exportした状態の違うTaskコンポーネントが左側のバーで選択でき、見た目の違いがわかります。
デフォルト状態:
ピン(星マークがついている)状態:
アーカイブ状態:
拡張 (Addon)
Storybookは拡張できるようになっています。公式の拡張をいくつか紹介します。
Actionsアドオン
クリックするとイベントが見れます。
Knobsアドオン
モックデータをGUIから変更できます。
StoryShotsアドオン
Snapshot Testingをするアドオンです。ストーリーごとにスナップショットが作られます。スナップショットとはコンポーネントに与えたインプットに対するアウトプット(レンダリングされたもの)です。画像を取るわけではなくレンダリング結果のHTMLを記録する感じです。Snapshot Testingは記録されている状態から変更があると自動で検知して表示します。例えばTaskコンポーネントの変更でアウトプットが変わると、元のスナップショットと比較されて変更部分が出力されます。Visual Testingでは目視でデグレを確認しますが、StoryShotsで変更部分が出力されるのでその部分だけ確認すれば効率的に確認ができます。
ユニットテスト
Storybookのモックデータを与えてexportするという形式はユニットテストと相性が良いです。ただ変更に脆くメンテナンスが大変なため、可能な限りVisual Test、Snapshot Test、Visual regression testを使うようにすると良いようです。
コンポーネント駆動開発
コンポーネント(部分)→ページへ(全体)という流れで開発する手法です。Storybookでよりやりやすいと思います。
Visual regression testing
Storybookでコンポーネントごとの見た目がわかるので、例えばプルリクエストを出した時に、PR前後の見た目の差分を見てデグレが起きてないかを確認できます。これをVisual regression testingと言います。この時の流れは次のようになります。
- Storybookを立ち上げる
- ヘッドレスブラウザでスクリーンショットを撮る
- PR前後を画像で比較し差分を表示
- レビュワーが確認
これをやってくれるツールにはreg-suitなどがあります。SaaS型にはChromaticがあります。
Storybookのデメリット
メンテナンスコストがかかることが大きそうです。
参考
この記事はLearn StorybookのIntro to Storybookをやってみたまとめでした。Storybookメンテナーの方が作っているようでわかりやすくありがたいです。
おわりに
メンテナンスコストはかかりますが、継続的に改善するようなサイトでは信頼性を保てるし、Storybookでデザイナやプランナーともコミュニケーションできそうなので良いのではと思いました*3。