iRidge Advent Calendar 2018 の9日目の記事です。
Nuxt.jsとElementUIを使ったSPA開発にStroyBookを導入した話を書きます。
はじめに
チームでコンポーネント開発する場合、レビュー時にデザインを確認しにくい課題がありました。
コンポーネント自体はAtomic Designに則っているため、Atomsなどの実装はページに書き出されていないです。
そのため、レビューして確認するときは以下のフローを取っていました。
- レビュー対象のブランチをpullする
- コンポーネントをページに書き出す
- 開発環境を起動する
- デザインを確認する
コンポーネントごとにレビューできるツールを探していたら、StoryBookに出会ったため導入方法をまとめます。
セットアップ
StoryBookはCLIで簡単にセットアップできます。
StoryBook CLIのインストール
$ yarn add -g @storybook/cli
Nuxtプロジェクトに追加
プロジェクトルートで getstorybook
コマンドを実行します。
$ cd nuxtproject/
$ getstorybook
sb init
sb init - the simplest way to add a storybook to your project.
• Detecting project type. ✓
• Adding storybook support to your "Vue" app. ✓
• Preparing to install dependencies. ✓
yarn install v1.10.1
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
[4/4] 📃 Building fresh packages...
success Saved lockfile.
✨ Done in 97.05s.
• Installing dependencies. ✓
完了するとプロジェクト配下に .storybook
および stories/
が作成されます。
.storybook/config.js
はプラグインの追加やストーリーファイルの対象を設定できます。
ストーリーはstories/
以下に記述していきます。
webpackの設定
Vue(Nuxt)を利用するにはwebpackの設定を追加します。
以下ではSFCの style
やElementUIのフォント系をバンドルするための設定を追加してます。
const path = require("path");
const rootPath = path.resolve(__dirname, '../');
module.exports = {
module: {
rules: [
{
test: /\.css?$/,
loaders: ['style-loader', 'css-loader']
},
{
test: /\.scss$/,
loaders: ['style-loader', 'css-loader', 'sass-loader']
},
{
test: /\.(png|jpe?g|gif|svg)$/,
loader: 'url-loader',
query: {
limit: 1000, // 1kB
name: 'img/[name].[hash:7].[ext]'
}
},
{
test: /\.(otf|eot|svg|ttf|woff|woff2)(\?.)?$/,
loader: 'url-loader'
}
]
},
resolve: {
extensions: ['.vue'],
alias: {
'@': rootPath,
'~': rootPath,
}
}
};
StoryBookを起動する
ここまできたらpackage.json
に登録されている storybook
コマンドを実行してみましょう。
$ yarn storybook
Exampleのコンポーネントがストーリーに登録されているのを確認できると思います。
ElementUIを組み込む
StoryBookにElementUIを組み込むにはNuxtのプラグインと同様の設定をする必要があります。
.storybook/config.js
にElementUIのJS部分とスタイルのインポートを行います。
import { configure } from '@storybook/vue';
+ import '!style-loader!css-loader!element-ui/lib/theme-chalk/index.css'; // ElementUIのスタイルのロード
+ import ElementUI from '../plugins/element-ui'; // ElementUIのコア部分のロード
+ ElementUI();
// automatically import all files ending in *.stories.js
const req = require.context('../stories', true, /.stories.js$/);
function loadStories() {
req.keys().forEach(filename => req(filename));
}
configure(loadStories, module);
ストーリーを書く
ElementUIの設定が完了したら、実際にストーリーを書いていきましょう。
ストーリーを書く前にElementUIのボタンコンポーネントを作成します。
<template>
<div>
<el-button :type="type">
{{ title }}
</el-button>
</div>
</template>
<script>
export default {
name: 'ButtonEl',
props: {
type: {
type: String,
required: true,
default: ''
},
title: {
type: String,
required: true,
default: ''
}
}
}
</script>
ストーリーは以下になります。
import { storiesOf } from '@storybook/vue'
import ButtonEl from '@/components/atoms/ButtonEl.vue'
storiesOf('ButtonEl', module)
.add('default button', () => ({
components: { ButtonEl },
template: '<button-el title="タイトル" type="default" />'
}))
.add('custom button', () => ({
components: { ButtonEl },
template: '<button-el title="新規登録" type="primary"/>'
}))
StoryBookを起動するとストーリーが追加されているのがわかります。
StoryBookをデプロイする
レビュー時にローカル環境でStoryBookを起動するだけでコンポーネントのデザインが確認できるところまできました。
しかし、ローカル環境で起動するのは手間です。
そこでGitLab CIを使ってリポジトリにPushするとStoryBookをデプロイするフローを作ってみました。
完成した .gitlab-ci.yml
は以下になります。
stages:
- storybook-build
- storybook-deploy
build_storybook:
image: node:10.13.0
stage: storybook-build
script:
- yarn install
- yarn build-storybook
artifacts:
paths:
- storybook-static
deploy_storybook:
image: python:3.7
stage: storybook-deploy
before_script:
- pip install awscli
script:
- aws s3 sync ./storybook-static/ s3://{{バケット名}}/$CI_COMMIT_REF_NAME/
StoryBookのビルドコマンドはpackage.json
に登録されています。
ビルドが完了すると storybook-static
ディレクトリ以下にファイルが作成されます。
ホスティング先にはS3バケットを使用しました。
リポジトリにPushしたら新しいディレクトリを作成してデプロイするようにしています。
ディレクトリ名はブランチ名を流用していて、GitLab CIの環境変数 CI_COMMIT_REF_NAME
を使っています。
まとめ
NuxtのプロジェクトにStoryBookを導入してみました。
導入は思ったよりも簡単ですが、getstorybook
時にwebpackの設定を追加してくれるとありがたいです。
今後はreg-suit
と組み合わせてVisual Regression Testing を実施してみたいです。