Storybook for Vueでエンジニアとデザイナーの協業を加速させる

この記事はCAMPHOR- Advent Calendar 2017の23日目の記事です。

はじめに

アプリケーションの機能を「カプセル化」、「コンポーネント化」しようというのは、フロントエンド/バックエンド問わずに近年のWeb開発におけるトレンドのひとつです。

Web業界も5年もの、10年ものと呼ばれるシステムが増える中で「最初から完璧なシステムを作ることなんて無理なんじゃないか」と多くの人が気づきはじめました。 その流れを受けて「どうせ改修が必要なら、小さなスコープで新しいものに置き換え可能な仕組みを作ろうぜ!」というのが「カプセル化」、「コンポーネント化」の大きなモチベーションであると、個人的には理解しています。

Vue.jsとコンポーネント

JavaScriptフレームワークであるVue.jsも、例に漏れずコンポーネントドリブンな開発に適した仕組みの1つです。

SFC(Single File Component)として知られる .vueファイルに templatescriptを切り離せるだけでなく、 Scoped CSSの仕組みを用いてスタイリングでさえ1つのコンポーネントに限定して適用できるなど、非常に再利用性の高いコンポーネント設計が行えて重宝しています。

またVue.jsの大きな特徴として、既存のHTMLとさほど変わらないシンタックスコンポーネントが記述できるという点が挙げられます(もちろんJSXで記述することもできます)。HTMLやCSSについての基本を抑えていればJSが苦手なWebデザイナーさんにも作成・改修依頼が投げられるというのは、常に人材不足に泣かされる中小Web制作会社としては非常にありがたいですね!

今回紹介するSrotybook for Vueは、そんな現場レベルでデザイナーさんとフロントエンドエンジニアの協業を加速させるためのツールです。

Storybookとは

Storybookとは、iframeを用いたサンドボックス上でコンポーネントの挙動をチェックできるUI開発環境です。ただのテストツールとしてではなく、スタイルガイドとしての利用も想定されているため、エンジニアだけでなくデザイナーさんにも役立つツールとして期待されています。

github.com

StorybookはもともとReactユーザー向けのツールでしたが、 v3.2.0からVueもサポートされ、現在はReact Native Webにも対応しました。

事例諸々

公式ページより様々な企業の導入事例を見ることができます。

https://storybook.js.org/examples/

f:id:andoshin11:20171222172336p:plain

各社ユニークなStorybookを用意していて眺めているだけで面白いです。会社の顔にもなるようなスタイルガイドを簡単に作れるなんてワクワクしますね。

今回はこのStorybookの導入 → Storyと呼ばれるStorybook内のページにVueコンポーネントを追加するまで、の流れを追っていきたいと思います。

本記事の対象

  • ES6分かるマン/ウーマン
  • Vue.jsなんとなく分かるマン/ウーマン
  • Storybookにとりあえず興味あるマン/ウーマン

本記事のゴール

いつも前置きが長く申し訳ないですが、本記事は以下のことを目的として書かれています

  • Storybookの概要を知ってもらう
  • 「Storybook、意外とカンタンやん!」と思ってもらう
  • 社内で投入する前に個人的に試した内容の作業ログを残したい

まぁ、ほとんど3つ目がメインです。それでは上記を踏まえた上で早速Storybookを動かしてみましょう。

Storybookを導入する

まずはvue-cliでアプリを作成

$ vue init webpack sample // console上で対話しながらアプリケーションを作成
$ cd sample
$ yarn
$ yarn run dev

Storyobookの公式ページにはQuick start guideの他に、Slow start guideというページが用意されているので今回はそちらを参考にします。

$ yarn add -D @storybook/vue // devDependenciesにstorybookを追加

Yarn scriptに起動コマンドを記述

{
  "scripts": {
    "storybook": "start-storybook -p 9001 -c .storybook"
  }
}

.storybook/config.jsに設定を記述

import { configure } from '@storybook/vue'

// ストーリーの読み込み
function loadStories() {
  require('../src/stories')
}

configure(loadStories, module)

読み込むStoryを作成する前に、ボタンを表示するコンポーネントを雑に用意します

<template>
  <button>Hello Vue</button>
</template>
<style scoped>
  button {
    color: green;
    border-radius: 5px;
    font-size: 18px;
    line-height: 1.5;
    padding: 0 10px;
  }
</style>

上記コンポーネントを表示するStoryを作成

// src/stories/index.js
import { storiesOf } from '@storybook/vue'

import MyButton from '../components/MyButton.vue'

storiesOf('Buttons', module)
  .add('simple', () => ({
    components: { MyButton },
    template: '<MyButton/>'
  }))

Yarn scriptで Storybookを起動

yarn storybook

ブラウザで localhost:9001にアクセスしてStorybookが表示されていることを確認します

f:id:andoshin11:20171217165029p:plain

無事にコンポーネントがiframe上に描画されました。

またWebpackのHMR(Hot Module Replacement)が有効になっているので、コンポーネントファイルを編集すると変更が動的に反映されることが確認できます。

Addonsを使う

このままでは少し寂しいのでStorybookにAddonsを追加して機能や見た目を拡張していきましょう

Storybook Addon Actions

Storybook Addon Actionsイベントハンドラから渡ってきたデータの確認やロギングができるAddonです。

github.com

Yarnでインストール

$ yarn add -D @storybook/addon-actions

新しくAddonsを追加する際は .storybook/addons.jsに追記する必要があります

// .storybook/addons.js
import '@storybook/addon-actions/register'

Addonから action関数をimportして、ボタンの onClickイベントと紐づけてみます

import { storiesOf } from '@storybook/vue'
import { action } from '@storybook/addon-actions'

import MyButton from '../components/MyButton.vue'

storiesOf('Buttons', module)
  .add('simple', () => ({
    components: { MyButton },
    template: '<MyButton @click.native="action"/>',
    methods: { action: action('button-clicked') },
  }))

コンポーネント@clickに対して .native修飾子をつけると、root要素のイベントを監視できるんですね。初めて知りました。

上記のコードを確認してみます

Storybook内に「ACTION LOGGER」というパネルが表示され、コンポーネントのイベントにフックしたログが表示されるようになりました。これを活用すると、より細かくコンポーネントの挙動を確認することができますね!

storybook-addon-vue-info

storybook-addon-vue-infoは、コンポーネント情報の表示を改善してくれるAddonです

github.com

Yarnでインストール

$ yarn add -D storybook-addon-vue-info

Exampleを参考に decoratorとして実装

import { storiesOf } from '@storybook/vue'
import { action } from '@storybook/addon-actions'
import VueInfoAddon from 'storybook-addon-vue-info'

import MyButton from '../components/MyButton.vue'

storiesOf('Buttons', module)
  .addDecorator(VueInfoAddon)
  .add('simple', () => ({
    components: { MyButton },
    template: '<MyButton @click.native="action"/>',
    methods: { action: action('button-clicked') },
  }))

ついでに MyButton.vueも少し改修

<template>
  <button>{{ text }}</button>
</template>
<script>
  export default {
    props: {
      text: {
        type: String,
        default: 'Hello Vue'
      }
    }
  }
</script>

propsでボタンに表示するテキストを受け取るようにしました。デフォルトは "Hello Vue"にしています。この状態で表示チェック

f:id:andoshin11:20171222093101p:plain

このように、 decoratorをつけたStory内のコンポーネントについての使用例とコンポーネントの持つことができるprops等が体系的に表示されました!

お手軽便利系のAddonです。

Knobs

GUIからコンポーネントの持つプロパティの情報を更新できるAddonです。

github.com

Yarnでインストール

$ yarn add -D @storybook/addon-knobs

addons.jsに追記

import '@storybook/addon-knobs/register'

decolatorとしてStoryに追加します。今回は propsとして labelbackgroundColorを受け取る ButtonWarningコンポーネントを用意しました

import { storiesOf } from '@storybook/react'
import { withKnobs, text, color } from '@storybook/addon-knobs'

import ButtonWarning from '@/js/components/ButtonWarning'

...

storiesOf('Buttons', module)
  .addDecorator(withKnobs)
  .add('warning', () => {
    const label = text('Label', 'Warning')
    const backgroundColor = color('Color', '#ffffff')
    return {
      components: { ButtonWarning },
      template: `<ButtonWarning label="${label}" backgroundColor="${backgroundColor}" />`
    }
  })

text(), color()という関数を利用することで、それぞれの値に対する inputフォームのようなUIが表示されるようになります

色の調整や文字列の変更が誰でもできるようになって最高 :clap::clap:

Links

Story内から別のStoryを表示する(遷移する)ためのAddon。

github.com

詳細は割愛

その他のAddon

基本的にUIをスッキリさせる系のAddonsが多い印象ですが、今回は全て試せませんでした。公式にGalleryが用意されているので、興味のある方は以下のリンクからご確認ください。痒いところに手がとどくAddonが見つかるかもしれません

https://storybook.js.org/addons/addon-gallery/

実際に使ってみた

手元にあったコンポーネントを突っ込んで作成したStorybookがこちらになります

デザイナーはすぐに見た目のレビューができるし、エンジニアはデザインの変更を差分で管理できるしで、なかなか幸せな世界に近づいたのではないでしょうか

まとめ

Storybook本体のVue.js対応が行われたばかりということもありまだVue.jsに対応していないAddonsが多いようですが、スタイルガイドとしては必要十分な仕組みが備わっているように感じました。

最初の設定はクセがありますが、一度導入してしまえば機械的コンポーネントを追加していくだけなので中規模以上のSaasを運用するケース、受託案件を小さく大量に回すケース、どちらでも活用できるのではと思います。

社内での本格的な実践投入はこれからですが、再利用可能なコード資産が1つでも多く残せるよう時間をかけて育てていきたいです。

明日はohmurakenの記事です。お楽しみに!