Storybookをまず動かす!ReactとVueの最小環境を作った

最近Storybookを会社で導入していて、環境設定についてまとめました。
基本的には、公式サイトのとおりですが、コンポーネントの例の記載がなかったり、ReactとVueでできるものが異なったりして、困った部分が合ったので、すぐに動く環境を作りました。

github.com

本エントリのコードはNode v8.9.4の環境で動作を確認しています。

Storybook?

f:id:zuckey_17:20180222101257p:plain

https://storybook.js.org/

The UI Development Environment

ReactやVueなどのUIライブラリで作成したコンポーネントの動作やデザインをエンジニア、デザイナ間で共有、閲覧できるツールです。
Storybookという名前の通り、あるコンポーネントコンポーネントの集合に対して、storyを複数用意し、storyごとの振る舞いを閲覧することができます。

環境構築

StorybookはReact、Vueの場合それぞれ、内部的にWebpackを利用しています。
このエントリで紹介しているものを動かすためには特別な設定は必要ありませんが、必要に応じてWebpackの設定をすることもできます。

Storybook - Custom Webpack Config

f:id:zuckey_17:20180222041649g:plain

動くサンプルはこちら↓

https://zuckeym-17.github.io/storybook-sample

Reactの場合

1. プロジェクトフォルダを作成、npm init

mkdir storybook-sample
cd react-storybook-sample
npm init

2. StorybookとReactについて必要なライブラリを追加

@storybook/reactおよび、reactreact-dombabel-coreを追加する必要があります。

npm i --save-dev @storybook/react
npm i --save react react-dom
npm i --save-dev babel-core

3. Storybookの環境を立ち上げるnpmスクリプトを追加

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

ここでpacage.jsonの全容は以下のようになります。
https://github.com/zuckeyM-17/storybook-sample/blob/master/react-storybook-sample/package.json

4. Storybookの設定ファイルを作成

Storybookは設定ファイルを.storybookというディレクトリに置きます。
最小環境では、Storybookにstoryの場所を伝える設定を.storybook/config.jsに書くだけです。
以下では、stories/index.jsを読み込むという設定をしています。

import { configure } from '@storybook/react';

function loadStories() {
    require('../stories/index.js'); // 好きな場所のstoryをrequireできます。
}

configure(loadStories, module);

5. Reactのコンポーネントを作成

ボタンの中身と、クリック時のメソッドをPropsとして渡せる単純なコンポーネントを作成します。
components/Button.jsxとして以下を保存します。

import React from 'react';

const Button = ({onClick, children}) => {
  return (
    <button onClick={onClick}>{children}</button>
  );
};

export default Button;

6. storyを作成

ここまでいけばあとはstoryを書くことができます。
ストーリーはいわば、そのコンポーネントの初期状態です。

import React from 'react';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import Button from '../components/Button';

storiesOf('Button', module)
  .add('with text', () => (
    <Button onClick={action('clicked')}>Hello Button</Button>
  ))
  .add('with some emoji', () => (
    <Button onClick={action('clicked')}>😀 😎 👍 💯</Button>
  ));

7. Storybookの起動と確認

これで準備は完了です。
以下のコマンドにてStorybookを起動し、localhost:9001にアクセスしてみましょう。

npm run storybook

Vueの場合

1. プロジェクトフォルダを作成、npm init

mkdir storybook-sample
cd vue-storybook-sample
npm init

2. StorybookとVueについて必要なライブラリを追加

@storybook/vueおよび、vuebabel-coreを追加する必要があります。

npm i --save-dev @storybook/vue
npm i --save vue
npm i --save-dev babel-core

3. Storybookの環境を立ち上げるnpmスクリプトを追加

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

ここでpacage.jsonの全容は以下のようになります。
https://github.com/zuckeyM-17/storybook-sample/blob/master/vue-storybook-sample/package.json

4. Storybookの設定ファイルを作成

Storybookは設定ファイルを.storybookというディレクトリに置きます。
VueのStorybook最小構成では、

  • Storybookにstoryの場所を伝える設定: .storybook/config.js
  • Storybookに用意されているaddonを使う宣言: .storybook/addons.js

をそれぞれ用意する必要があります。

.storybook/config.js

stories/index.jsを読み込むという設定をしています。

import { configure } from "@storybook/vue";

import Vue from "vue";

function loadStories() {
  require("../stories/index.js");
}

configure(loadStories, module);

.storybook/addons.js

@storybook/addon-actionsという、イベントハンドラのコールバック関数として設定し、そのイベントが発火したことをロギングするためのaddonを利用する旨を設定します。

import '@storybook/addon-actions/register';

5. Vueのコンポーネントを作成

ボタンの中身と、クリック時のメソッドをPropsとして渡せる単純なコンポーネントを作成します。
components/Button.vueとして以下を保存します。

<template>
  <button @click="handleClick">{{ children }}</button>
</template>

<script>
import Vue from "vue";

export default Vue.extend({
  props: ["handleClick", "children"],
});
</script>

6. storyを作成

ここまでいけばあとはstoryを書くことができます。
ストーリーはいわば、そのコンポーネントの初期状態です。

import Vue from "vue";
import { storiesOf } from "@storybook/vue";
import { action } from '@storybook/addon-actions';
import MyButton from "../components/Button.vue";

storiesOf("Button", module)
  .add("with text", () => ({
    components: { MyButton },
    data() {
      return {
        handleClick: action("clicked"),
        children: "hello button"
      };
    },
    template: '<my-button :handleClick="handleClick" :children="children"></my-button>'
  }))
  .add("with some emoji", () => ({
    components: { MyButton },
    data() {
      return {
        handleClick: action("clicked"),
        children: "😀 😎 👍 💯"
      };
    },
    template: '<my-button :handleClick="handleClick" :children="children"></my-button>'
  }));

7. Storybookの起動と確認

これで準備は完了です。
以下のコマンドにてStorybookを起動し、localhost:9001にアクセスしてみましょう。

npm run storybook

まとめ

ReactとVueで同じStorybookが動くサンプル環境を作ってみました。
コードベースも基本的に記事中のものが全てですので、是非一度動かしてみていただければなと思います。

おまけ

グローバルなCSSなど

Reset CSSなど、コンポーネントに当てるCSSとは別にグローバルになにかコンテンツを読み込んでおきたいということがあると思います。
その際は、設定ファイル置き場である.storybookpreview-head.htmlを作成し、HTMLのheaderに追加したいタグを書くことができます。

例)Reset CSS、Font AwesomeのJSをCDNから利用する

<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/3.18.1/build/cssreset/cssreset-min.css">
<script defer src="https://use.fontawesome.com/releases/v5.0.6/js/all.js"></script>