はじめに
この記事では Storybook の始め方からプロジェクト導入までの手順をざっくり解説した記事です。「Storybook ってなにがええねん」「どうやってプロジェクトで使うねん」と使い始めた当初ちんぷんかんぷんだったので、(おまけに参考サイトが英語の記事ばっかりでしんどい)、少しでも役に立てばいいなと思い記事にまとめてみました。
Storybook 自体に関する詳細や具体的な運用手順は、すでにわかりやすい記事がたくさんあると思うので、最低限の説明にとどめています🙇♂️
前提
- 今回は本プロジェクトとは別に「Storybook用のリポジトリ」(つまりコンポーネントを管理するだけのリポジトリ)を作成して運用して行きます。理由は後述します。
- Storybook を導入するプロジェクトは既に存在している前提で話は進みます
Storybook とは
UIコンポーネントのカタログを作るツール
わかりやすかった記事
https://www.ey-office.com/blog_archive/2020/11/18/storybook-is-good-tool/
Storybook 導入の経緯
どのファイルがどんな見た目してるのかぱっと見じゃわからん
自分が現在参画してるプロジェクトは、ある程度画面が出来上がった状態でアサインされました。最初に画面実装を任せてもらったのですが、とにかくコンポーネント数が多く、カンプ通りに実装するために
- このコンポーネントはすでに作成されてる、、?
- 似たような見た目やけど絶妙に見た目が違う、、?
- props がいっぱいあるけど、どの props を渡したらどんな表示になるん、、?
というのを確認するのにかなりの時間がとられてしまいました。挙句の果てにめんどくさくなって既に存在するコンポーネントをわざわざ作成したりもしました(ごめんなさい)
Storybook を使えばそんな問題もすぐに解決できちゃいます。
You can use args in your stories to configure the component's appearance, similar to what you would do in an application.
引数を渡すことで外観を変更することができる
別のプロジェクトでも似たようなコンポーネントを作成するので、使いまわせるものは使いまわしたい
実は自分がアサインされたプロジェクトとは別で、同じクライアント様から別の案件も受注してるらしいのですが、何と似たような UIになってるではありませんか! Storybook では 「1つの Storybook を複数のプロジェクトで共有する」なんてこともできてしまうので、導入しない手はありませんね。
Storybook をインストール
前置きが長くなってしまいましたが、Storybook を導入してみましょう。今回は複数プロジェクトで使い回すことを前提とするので、プロジェクトとは別に Storybook 用のリポジトリを作成します。
Nuxt のプロジェクトを作成
npm init nuxt-app nuxt-storybook
cd nuxt-storybook
npm run dev
詳細は割愛、、
https://nuxtjs.org/ja/docs/get-started/installation
Nuxt に Storybook を入れる
npm install --save-dev @nuxtjs/storybook postcss@latest
Storybook の詳細設定は nuxt.config,js から行えます。
今回は一旦 stories フォルダ以下の storie.js は全てインポートする、という設定だけ追記しておきます。
storybook: {
stories: ['~/stories/**/*.stories.js'],
},
他にもオプションがあるので必要に応じて追加してみてください!
https://storybook.nuxtjs.org/api/options
ここまでできたら Github のリポジトリを作成、push し、Storybook が立ち上がるかも確認しておきましょう。
npx nuxt storybook
公式通りに進めればこれで 3003番ポートが立ち上がり、Storybook が表示されます。
コンポーネントを作成し、Storybook に表示させる
作成したコンポーネントを Storybook で表示させてみましょう。イメージとしては、「UIカタログにコンポーネントを掲載する」ことをゴールとします。
① コンポーネントを作成
なにはともあれコンポーネントを作成しましょう。
今回は簡単な複数のカラーバリエーションが存在するボタンを作成します。
<div>
<button
class="app-button"
:class="{
'-red': red,
'-blue': blue,
}"
>
Button
</button>
</div>
② 作成したコンポーネントを Storybook に組み込む
import AppButtonComp from '@/components/atoms/AppButton'
export default {
title: 'Components/Button',
component: AppButtonComp,
argTypes: {
red: false,
blue: false,
},
}
const AppButton = (_args, { argTypes }) => ({
components: AppButtonComp,
template: `
<AppButton
v-bind="$props"
/>
`,
props: Object.keys(argTypes),
})
// デフォルト表記
export const Default = AppButton.bind({})
// ボタンを赤くする
export const Red = AppButton.bind({})
Red.args = {
...Default.args,
red: true,
}
// ボタンを赤くする
export const Blue = AppButton.bind({})
Blue.args = {
...Default.args,
blue: true,
}
argTypes の中で引数を指定し、props や action(イベント)を作成することができます。
詳細: https://storybook.js.org/docs/react/api/argtypes
ここまで行うと Storybook 上で作成したコンポーネントを見ることができます。
これでどのコンポーネントがどんな形をしてるのか、どういう props を受け取り何パターンに変化するのかが視覚的にわかるようになりました。
プロジェクト側で呼び出す
Storybook を導入したものの、プロジェクト側でどうやって呼び出せばいいのでしょう。 Storybook のリポジトリからわざわざ Vue ファイルと cssファイルをコピペすれば使えますが少し面倒ですね。そこで先輩にご相談したところ、npm package
と git submodules
を2つのやり方が主流らしく、今回は導入コストの低そうな git submodules
で実装していくことにしました。
git submodules とは
git submodule は、外部の リポジトリを、プロジェクトの git リポジトリのサブディレクトリとして登録し、特定の commit を参照する仕組みのことです。
git submodule に関してはこちらの記事に詳しくまとめられていたのでよければご覧ください
https://qiita.com/sotarok/items/0d525e568a6088f6f6bb
今回は「ビルドした時に、Submodulesの components ディレクトリと css ディレクトリを、本 projectのフォルダにコピーしてくる」 ように設定して行きます。
build したときに Storybook リポジトリからコピー
最初に npm script が走った時にファイルをコピーできるよう cpx パッケージをインストールしましょう。
$ npm install --save-dev cpx
参考 https://maku77.github.io/nodejs/npm/npm-run-copy-file.html
次に package.json に以下のコマンドを追記して行きます。
今回はわかりやすくするために小分けにしています。
// Submodules 内の storybook用リポジトリから最新のコミットを pull
"pull": "cd storybook-repo && git pull origin main",
// Submodules 内の storybook用リポジトリからコンポーネントをコピー
"copy:component": "cpx 'storybook-repo/components/**' 'src/components/'",
// Submodules 内の storybook用リポジトリからコンポーネントをコピー
"copy:scss": "cpx 'storybook-repo/assets/scss/components/**' 'src/assets/scss/components'",
このコマンドを随時実行してもいいのですが、面倒くさいのでビルドした時に実行してみます。
"dev:story": "npm run pull && npm run copy:component && npm run copy:scss && npm run copy:image && nuxt",
これでビルドするたびに submodules から呼び出せるようになりました!
参考
https://www.ey-office.com/blog_archive/2020/11/18/storybook-is-good-tool/
https://storybook.js.org/docs/react/writing-stories/args#args-can-modify-any-aspect-of-your-component
https://storybook.js.org/tutorials/design-systems-for-developers/react/en/distribute/
https://maku77.github.io/nodejs/npm/npm-run-copy-file.html