Storybookの使い方(導入, Storyの定義, Addon)

UIコンポーネントの開発環境である「Storybook」の利用方法について確認します。「CLIを利用したStorybookの導入方法」「Storyの定義方法」「Addonによる機能拡張」など取り上げます。

作業環境

OSはMacです。以下の環境で作業します。

$ node -v
v11.4.0
$ yarn -v
1.13.0

CLIでお手軽導入

Storybookが提供しているCLIを利用すると、プロジェクトで利用しているライブラリ( React Vue.js など)を判定して、ライブラリに合ったセットアップを行なってくれます。

対象プロジェクト配下で下記コマンドを実行します。

npx -p @storybook/cli sb init

Reactプロジェクトに導入

create-react-app で作成したプロジェクト配下に移動して、Storybookを導入します。

$ npx -p @storybook/cli sb init
npx: installed 462 in 27.926s

 sb init - the simplest way to add a storybook to your project.

 • Detecting project type. ✓
 • Adding storybook support to your "Create React App" based project. ✓
 • Preparing to install dependencies. ✓

yarn install v1.13.0
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
warning " > babel-loader@8.0.5" has unmet peer dependency "webpack@>=2".
warning "react-scripts > pnp-webpack-plugin > ts-pnp@1.0.0" has unmet peer dependency "typescript@*".
warning "@storybook/react > @emotion/styled > @emotion/styled-base@0.10.6" has unmet peer dependency "@emotion/core@0.x.x".
[4/4] 🔨  Building fresh packages...
success Saved lockfile.
✨  Done in 64.57s.

 • Installing dependencies. ✓

To run your storybook, type:

   yarn storybook

For more information visit: https://storybook.js.org

下記変更がありました。

$ git diff HEAD --compact-summary
 .storybook/addons.js (new) |    2 +
 .storybook/config.js (new) |    7 +
 package.json               |   14 +-
 src/stories/index.js (new) |   19 ++
 yarn.lock                  | 2219 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
 5 files changed, 2153 insertions(+), 108 deletions(-)
$ git diff HEAD -- package.json
diff --git a/package.json b/package.json
index 181a723..766f102 100644
--- a/package.json
+++ b/package.json
@@ -11,7 +11,9 @@
     "start": "react-scripts start",
     "build": "react-scripts build",
     "test": "react-scripts test",
-    "eject": "react-scripts eject"
+    "eject": "react-scripts eject",
+    "storybook": "start-storybook -p 9009 -s public",
+    "build-storybook": "build-storybook -s public"
   },
   "eslintConfig": {
     "extends": "react-app"
@@ -21,5 +23,13 @@
     "not dead",
     "not ie <= 11",
     "not op_mini all"
-  ]
+  ],
+  "devDependencies": {
+    "@storybook/react": "^4.1.11",
+    "@storybook/addon-actions": "^4.1.11",
+    "@storybook/addon-links": "^4.1.11",
+    "@storybook/addons": "^4.1.11",
+    "@babel/core": "^7.3.3",
+    "babel-loader": "^8.0.5"
+  }
 }

Vue.jsプロジェクトに導入

Vue CLI で作成したプロジェクト配下に移動して、Storybookを導入します。

$ npx -p @storybook/cli sb init
npx: installed 462 in 31.642s

 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.13.0
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
warning " > babel-loader@8.0.5" has unmet peer dependency "webpack@>=2".
warning " > @storybook/vue@4.1.11" has unmet peer dependency "vue-loader@>=15.x.x".
warning "@storybook/addon-actions > @emotion/provider@0.11.2" has unmet peer dependency "react@>=16.3.0".
warning "@storybook/addon-actions > @emotion/core@0.13.1" has unmet peer dependency "react@>=16.3.0".
warning "@storybook/addon-actions > @storybook/components@4.1.11" has unmet peer dependency "react@*".
warning "@storybook/addon-actions > @storybook/components@4.1.11" has unmet peer dependency "react-dom@*".
warning "@storybook/addon-actions > react-inspector@2.3.1" has unmet peer dependency "react@^0.14.0 || ^15.0.0 || ^16.0.0".
warning " > @storybook/addon-actions@4.1.11" has unmet peer dependency "react@*".
warning " > @storybook/addon-links@4.1.11" has unmet peer dependency "react@*".
[4/4] 🔨  Building fresh packages...
success Saved lockfile.
✨  Done in 30.48s.

 • Installing dependencies. ✓

To run your storybook, type:

   yarn storybook

For more information visit: https://storybook.js.org

下記変更がありました。

$ git diff HEAD --compact-summary
 .storybook/addons.js (new)     |    2 +
 .storybook/config.js (new)     |    9 +
 package.json                   |   13 +-
 stories/MyButton.js (new)      |   29 ++
 stories/Welcome.js (new)       |  121 +++++++++
 stories/index.stories.js (new) |   36 +++
 yarn.lock                      | 1891 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
 7 files changed, 2022 insertions(+), 79 deletions(-)
$ git diff HEAD -- package.json
diff --git a/package.json b/package.json
index bb05b41..0ef5b1a 100644
--- a/package.json
+++ b/package.json
@@ -5,7 +5,9 @@
   "scripts": {
     "serve": "vue-cli-service serve",
     "build": "vue-cli-service build",
-    "lint": "vue-cli-service lint"
+    "lint": "vue-cli-service lint",
+    "storybook": "start-storybook -p 6006",
+    "build-storybook": "build-storybook"
   },
   "dependencies": {
     "vue": "^2.5.22"
@@ -17,7 +19,14 @@
     "babel-eslint": "^10.0.1",
     "eslint": "^5.8.0",
     "eslint-plugin-vue": "^5.0.0",
-    "vue-template-compiler": "^2.5.21"
+    "vue-template-compiler": "^2.5.21",
+    "@storybook/vue": "^4.1.11",
+    "@storybook/addon-actions": "^4.1.11",
+    "@storybook/addon-links": "^4.1.11",
+    "@storybook/addons": "^4.1.11",
+    "babel-preset-vue": "^2.0.2",
+    "@babel/core": "^7.3.3",
+    "babel-loader": "^8.0.5"
   },
   "eslintConfig": {
     "root": true,

Storybook起動

以降、Vue.jsプロジェクトの方で作業を進めます。

yarn storybook を実行すると、Storybookが起動します。

$ yarn storybook
yarn run v1.13.0
$ start-storybook -p 6006
info @storybook/vue v4.1.11
info 
info => Loading presets
info => Loading presets
info => Loading custom addons config.
info => Using default webpack setup.
webpack built 4b5ca19b39113c2542fd in 9667ms                                                                            
╭───────────────────────────────────────────────╮
│                                               │
│   Storybook 4.1.11 started                    │
│   13 s for manager and 11 s for preview       │
│                                               │
│   Local:            http://localhost:6006/    │
│   On your network:  http://10.0.1.2:6006/     │
│                                               │
╰───────────────────────────────────────────────╯
619-javascript-storybook_start.gif

http://localhost:6006/ にアクセスして確認できます。

Storybookを導入したときにサンプルとして作成されたStoryを確認できます。

WelcomコンポーネントButtonコンポーネント が存在して、Buttonコンポーネントの配下には3つの Story(表示パターン・状態) が存在しています。

Storyの定義方法

storiesOfメソッド, addメソッド
( Component, Storyの登録 )

Storybook導入時に生成された stories/index.stories.js を確認します。

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

import MyButton from './MyButton';
import Welcome from './Welcome';

storiesOf('Welcome', module).add('to Storybook', () => ({
  components: { Welcome },
  template: '<welcome :showApp="action" />',
  methods: { action: linkTo('Button') },
}));

storiesOf('Button', module)
  .add('with text', () => ({
    components: { MyButton },
    template: '<my-button @click="action">Hello Button</my-button>',
    methods: { action: action('clicked') },
  }))
  .add('with JSX', () => ({
    components: { MyButton },
    // eslint-disable-next-line no-unused-vars
    render(h) {
      return <my-button onClick={this.action}>With JSX</my-button>;
    },
    methods: { action: linkTo('clicked') },
  }))
  .add('with some emoji', () => ({
    components: { MyButton },
    template: '<my-button @click="action">😀 😎 👍 💯</my-button>',
    methods: { action: action('clicked') },
  }));
  • storiesOfメソッドComponent を登録してます。
  • addメソッドStory を登録してます。

この他に、addDecoratorメソッド もよく利用されます。表示するとき、中央寄せして表示 Paddingを入れて表示 といったことを実現できます。

設定ファイル
( .storybook/config.js )

Storybook実行時の設定ファイル( .storybook/config.js )について確認します。

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

// 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);

ここで、.stories.jsファイル を取り込んでいるようです。

storiesフォルダ配下 ではなく、srcフォルダ配下 でストーリーを作成したい場合、以下のように修正します。

const req = require.context('../src', true, /.stories.js$/);

「プロジェクト全体で利用するCSSをStorybookにも取り込みたい」といったときにも、このファイルを編集すれば良さそうです。
https://storybook.js.org/configurations/default-config/#css-support

Addonで機能拡張

.storybook/addons.js

AddonでStorybookの機能を拡張できます。 .storybook/addons.js で組み込まれたAddonを確認できます。

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

主なAddon

以下は Vue.js のサンプルStorybookで利用されているAddonです。( https://storybooks-vue.netlify.com/ )

619-javascript-storybook_addon.png
No Addon
1 options
2 storysource
3 notes
4 knobs
5 viewport
6 backgrounds

その他の主要なAddonについては以下ページで確認できます。
https://storybook.js.org/addons/addon-gallery/

CLI

start-storybook|Storybook起動

すでに確認済みですが、Storybook起動には start-storybook を利用します。

--helpオプション で使い方を確認できます。

$ yarn start-storybook --help
yarn run v1.13.0
$ /xxxx/my-vue-app/node_modules/.bin/start-storybook --help
Usage: start-storybook [options]

Options:
  -V, --version                 output the version number
  -p, --port [number]           Port to run Storybook
  -h, --host [string]           Host to run Storybook
  -s, --static-dir <dir-names>  Directory where to load static files from
  -c, --config-dir [dir-name]   Directory where to load Storybook configurations from
  --https                       Serve Storybook over HTTPS. Note: You must provide your own certificate information.
  --ssl-ca <ca>                 Provide an SSL certificate authority. (Optional with --https, required if using a self-signed certificate)
  --ssl-cert <cert>             Provide an SSL certificate. (Required with --https)
  --ssl-key <key>               Provide an SSL key. (Required with --https)
  --smoke-test                  Exit after successful start
  --ci                          CI mode (skip interactive prompts, don't open browser
  --quiet                       Suppress verbose build output
  -h, --help                    output usage information
✨  Done in 1.54s.

例えば、「ポート番号の指定」と「静的ファイルが存在するパスの指定」を行いたい場合、以下のようにします。

start-storybook -p 6006 -s public

build-storybook|静的App書き出し

build-storybook を利用して、静的Appを書き出すことができます。

--helpオプション で使い方を確認できます。

$ yarn build-storybook --help
yarn run v1.13.0
$ build-storybook --help
Usage: build-storybook [options]

Options:
  -V, --version                 output the version number
  -s, --static-dir <dir-names>  Directory where to load static files from
  -o, --output-dir [dir-name]   Directory where to store built files
  -c, --config-dir [dir-name]   Directory where to load Storybook configurations from
  -w, --watch                   Enable watch mode
  -h, --help                    output usage information
✨  Done in 1.95s.

試しに実行してみます。

$ yarn build-storybook
yarn run v1.13.0
$ build-storybook
info @storybook/vue v4.1.11
info
info clean outputDir..
info => Copying prebuild dll's..
info => Building manager..
info => Loading manager config..
info => Loading presets
info => Loading custom addons config.
info => Compiling manager..
info => manager built (16 s)
  (省略)
info => Building preview..
info => Loading preview config..
info => Loading presets
info => Using default webpack setup.
info => Compiling preview..
info => Preview built (12 s)
  (省略)
info => Output directory: /xxxx/my-vue-app/storybook-static
✨  Done in 30.26s.

storybook-staticフォルダ 配下に静的ファイルが生成されました。

参考