モノレポでstorybookを作成してAmplifyにデプロイ
以前storybookのデプロイを行なったので、その時の手順を記事にしておこうと思います。サンプルプロジェクトを作成して、React + TypeScriptの環境にstorybookを導入しAWS Amplifyにデプロイします。
今回サンプル用に作成したプロジェクトのgitです。
プロジェクトの作成
今回はサンプル用のプロジェクトを作成します。React + TypeScriptでmonorepo構造を取り、バンドラーにはviteを使います。プロジェクトの構成は以下のようになります。
sample-project
├── storybook
└── test-app
ルートディレクトリを作って、test-appという名前でサブプロジェクトを作成します。
mkdir sample-project && cd sample-project
yarn create vite
vi sample-project/package.json
{
"name": "sample-project",
"private": true,
"workspaces": {
"packages": [
"test-app",
"storybook"
]
}
}
yarn workspace test-app install
yarn workspace test-app dev
storybookのプロジェクトを作成して、動作確認を行います。
mkdir storybook && cd storybook
yarn init
npx storybook init --builder @storybook/builder-vite
yarn workspace storybook install
yarn workspace storybook storybook
最後の行のコマンドを実行すると、storybookが立ち上がるはずですが、自分の環境ではホスト名を指定しないとうまく開くことができませんでした。 sample-project/storybook/package.json を一部以下のように編集してホスト名を指定します
"scripts": {
"storybook": "start-storybook -h 0.0.0.0 -p 6006",
"build-storybook": "build-storybook"
}
デプロイ
ここまででサンプルアプリとstorybookの雛形ができたので、githubにリポジトリを作成して AWS Amplifyにデプロイしていきます。Amplify ホスティングの「使用を開始する」を押して、画面の手順に沿ってGithubのリポジトリの接続を行なっていきます。
「リポジトリブランチの接続」の画面では、monorepoを接続しますか?という項目があるのでチェックを入れて、下の入力欄には今回のフォルダ名である「storybook」と入力します。次のビルドの設定画面ではamplify.ymlを以下のように編集しました。
version: 1
applications:
- frontend:
phases:
preBuild:
commands:
- yarn install
build:
commands:
- yarn workspace storybook build-storybook
artifacts:
baseDirectory: storybook/storybook-static
files:
- '**/*'
cache:
paths:
- node_modules/**/*
buildPath: /
appRoot: storybook
上記に貼ったコードで無事にデプロイできました!
自分はamplify.ymlの書き方を間違えていて何度かエラーが発生しました。もしデプロイに失敗していた場合マネジメントコンソールからエラーを確認できます。amplify.ymlで指定されているパスなど、どこを起点にしたパスを書いたら良いのか分かりづらかったです。
ブランチを接続できると、次からはgitのmainブランチにpushすると自動でamplifyにデプロイしてくれます。
エイリアス
test-appとして作成したプロジェクト内にatoms/Buttonなどを作成して、storybookではそれらのcomponentをimportして表示します。その際にエイリアスがあるとimportのパス指定が楽になります。エイリアスの設定をするには以下の二つのファイルを編集します。
sample-project/storybook/.storybook/main.js
const path = require("path");
const { mergeConfig } = require("vite");
module.exports = {
...
viteFinal: async (config, { configType }) => {
return mergeConfig(config, {
root: "./",
resolve: {
alias: {
"@test-app/": path.resolve(__dirname, "../../test-app/src/") + "/",
},
},
});
},
};
sample-project/test-app/tsconfig.json
{
"compilerOptions": {
...
"paths": {
"@test-app/*": ["./test-app/src/*"]
}
},
}
感想
storybookがあるとどのような要素(コンポーネント)があるかすぐに分かります。開発者以外のデザイナーの人にもどのような要素があるのか伝わりやすいのでデザインを決める上で参考になる場合もあると思います。また以前作った要素や他の人が作った要素を重複して作ってしまうなどを防ぐこともできます。あまり重要では無いかも知れませんが、storybook自体の見た目が綺麗なのも魅力的に思いました。
コンポーネントに渡すデータや状態、色などを簡単に変更できるのでテストを行う上で役に立つと思います。storybookに要素を追加する作業の中で一度コンポーネントを見直すので、そこで要素の改善点に気づくこともありました。しかしパーツの数が増えるとその分だけstorybookに追加する必要があるので作業が大変でした。プロジェクトに導入するかどうかはメリットとデメリット考えて導入した方がいいと思います。