RareJob Tech Blog

レアジョブテクノロジーズのエンジニア・デザイナーによる技術ブログです

Nuxt.jsプロジェクトにStorybookを導入する

こんにちは。APP・UXチームの大谷です。約1年ぶりくらいの投稿です。

最近は家にいることが多いので、ちょっと時間がかかる料理でもしてみよう。。
と餃子を皮から作ったりしています。餃子の皮を作る時は、お湯より水を使って練った方がモチモチ感がでて美味しいです。自分の好みにあった配合と焼き方を研究していきたい。

さて、今回は表題の通りNuxt.jsプロジェクトにStorybookを導入する方法について書いていきたいと思います。

Storybookとは?

StorybookとはUIコンポーネントをカタログのように一覧表示できたり、振る舞いをテストできるオープンソースのツールです。

storybook.js.org

なぜやるか?

新しく始まったプロジェクトをきっかけに、コンポーネントの管理方法やデザイナーとの連携について改めて整理してみようということでStorybookの導入が検討されました。

デザインチーム/フロントエンドチームで事前に用途についても協議してみました。

  • デザインチーム
    • コンポーネントのチェック(どんな種類/どんな挙動か)
    • スタイルガイドの管理
  • フロントエンドチーム
    • コンポーネントのチェック(どんな種類/どんな挙動か)
    • デザインチームへの共有

両チームとも基本的にコンポーネントの管理/共有に使いたい(ボタンやフォーム単位のパーツについて)という意見だったので、ページ全体など大きい単位での表示テストの用途には使わず、まずは小さい単位でのコンポーネントの管理/共有・スタイルガイドとして活用していこうという内容で認識を合わせました。

さっそくStorybookを導入してみる

まずはNuxtのサンプルプロジェクトを作成します。

% yarn create nuxt-app sample-project

作成したプロジェクト内でstorybookを導入していきます。

yarn add -D @storybook/cli
yarn sb init --type vue

yarn storybook

f:id:kinokonotani5656:20200611100741p:plain
storybook initial

storybook/cliは現在のlatest版(5.3.19)を使っています。
無事Storybookが立ち上がりましたが、Nuxtアプリケーションの本体を立ち上げようとしたらエラーが発生してしまいました。

yarn run dev
Type checking in progress...
 ERROR  Failed to compile with 39 errors
* core-js/modules/es6.array.from in ./.nuxt/client.js, ./.nuxt/components/nuxt-link.client.js
 .............
To install them, you can run: npm install --save core-js/modules/es6.array.find core-js/modules/es6.array.from core-js/modules/es6.array.iterator core-js/modules/es6.date.to-string core-js/modules/es6.function.name core-js/modules/es6.object.assign  .............

core-jsでめちゃめちゃ怒られます。 Storybookを導入した時にbabelとcore-jsのバージョンで依存関係の問題が発生してしまうようです。解消するためにここでは明示的にcore-jsの2系を指定してインストールし直しました。

yarn add core-js@2

あとはstoriesファイルと設定を追加していきます。 今回はpropsやdescriptionを作るためのaddonも追加してみました。

yarn add -D @storybook/addon-knobs
yarn add -D storybook-addon-vue-info

addon有効にする設定を追加します。

// .storybook/addons.js
import 'storybook-addon-vue-info/lib/register';
import '@storybook/addon-knobs/register';

configファイルを追加します。

// .storybook/config.js
import { configure, addDecorator } from '@storybook/vue';
import { withKnobs } from "@storybook/addon-knobs";
import { withInfo } from 'storybook-addon-vue-info'

// xxx.stories.jsに対してaddonを反映
addDecorator(withInfo)
addDecorator(withKnobs);

// どのファイルを見るか設定する。今回は../components下のstoriesファイルを対象にする
configure(require.context('../components', true, /\.stories\.(js|ts)$/), module);

storiesファイルを作成。

import { storiesOf } from '@storybook/vue'
import { text, select } from '@storybook/addon-knobs'
// サンプルで作成したコンポーネント
import Button from '@/components/atoms/button/index.vue'

const stories = storiesOf('Buttons', module)

stories.add(
  'button sample story',
  () => {
    return {
      // 対象のコンポーネント設定
      components: { Button },
      props: {
        colorStyle: {
          type: String,
          default: select('colorType', ['green', 'orange'])
        },
        value: { type: String, default: text('default', 'sample') }
      },
    // 描画する内容を設定
      template: `<Button :value=value :colorStyle=colorStyle />`
    }
  },
  { info: true }
)

Buttonコンポーネントの表示を確認できるようになります。

f:id:kinokonotani5656:20200611100837p:plain

GitLab Pagesで公開

毎回環境を立ち上げなくてもいいようにGitLab Pagesで公開するようにしました。 masterにマージされたタイミングでGitLab Pagesを更新するようにしたgitlab-ci.ymlファイルの設定がこちらです。

image: node:latest

cache:
  paths:
  - node_modules/

pages:
  stage: deploy
  tags:
    - sample_runner
  only:
    - master
  before_script:
    - 'yarn install'
  script:
    - 'yarn build-storybook'
    - 'cp -pr storybook-static ./public'
  artifacts:
    paths:
      - public

最後に

今回は記載していませんが、Jestと連携してstoriesファイルのスナップショットテストをすることもできるようです。コンポーネントの管理/共有をするために便利なStorybookですが、更新せずに古くなってしまっては意味がないのでスナップショットテストと連携するなど必ず更新する仕組みをつくっていくことも課題になります。

実運用はまだはじまっていませんが、デザイナーとエンジニアお互いにとって幸せな開発環境にできれば良いなと思います!