Quantcast
Channel: モチベーションクラウド Advent Calendarの記事 - Qiita
Viewing all articles
Browse latest Browse all 25

Vue.js のコンポーネント用 Storybook を Single File Component (SFC) で書く

$
0
0

はじめに

はじめまして。Motivation Cloud 開発メンバーの新参者 @navy-field です。
この開発現場では、フロントエンジニアとデザイナー間、あるいはフロントエンジニア同士の円滑なコミュニケーションのために Storybook を活用しています(参考:デザイナーとStorybookをS3上で共有)。
本記事では、そんな中で発見した、VueコンポーネントのStorybookを書く上でちょっと便利な小技を紹介いたします。

よくあるVueコンポーネントのStoryの書き方

Vue.jsコンポーネントのStoryの書き方として、以下のようなパターンをよく見かけます。

test.story.js
import { storiesOf } from "@storybook/vue";
import Test from "./Test.vue";

storiesOf('Test', module)
  .add('story as a component', () => ({
    components: { Test },
    data () {
        return {
            message: "Hello!"
        };
    },
    template: `<test :msg="message"></test>`
  }));

オフィシャルのドキュメントにもこのような形で書かれていますが、この書き方には次のような不便な点があります。

  • templateが文字列としてJS内に書かれるのでエディタのハイライトや補完が効かない
  • StoryにCSSを当てたいときに別ファイルに定義したりテンプレート内にインラインで書く必要があり、たちまち複雑化する

Vue.jsのオフィシャルガイドに書かれているSFCのメリットの裏返しですね。

これら問題は、Story を Single File Component (以下 SFC) で書くことで解消できます。

Storybook の設定ファイル

SFCでStoryを書く前に、Storybookの設定ファイルを変更して.vueファイルで書かれたStoryを読み込むようにましょう。

config.js
import { configure } from '@storybook/vue';

const req = require.context('../../src/components', true, /.story.(vue|js)$/)

function loadStories () {
  req.keys().forEach(req)
}

configure(loadStories, module);

このようにrequire.contextをつかうことで、componentsディレクトリ以下にあるファイルのうち、名前が.story.vueまたは .story.js で終わるファイルを全てStorybookで読み込むことができます。

SFCで書き直したStory

上記 test.story.js をSFCで書き直したサンプルは以下の通りです。

test.story.vue
<template>
    <test :msg="message"></test>
</template>

<script>
import Vue from "vue";
import { storiesOf } from "@storybook/vue";
import Test from "./Test.vue";

const testStory = {
    components: {
        Test
    },
    data () {
        return {
            message: "Hello!"
        }
    }
};
export default testStory;

storiesOf("Test", module)
  .add("story as a single file component", () => testStory);
</script>

<template> 内の export default testStory; によって、 vue-loadertestStoryにtemplateを組み込んでくれます。
またその下の add() の第2引数の関数の戻り値にtestStoryを指定することで、このStoryをtemplateを含むコンポーネントとしてStorybookに渡すことができます。

これでめでたくStoryをSFCで書くことができました。

おわりに

Storybookで自前のコンポーネントカタログを作ってそのクオリティを徐々に上げていくと能率がアップするし、とても楽しいです。
他にもTypeScriptでStory書いたり、Storyの整理術とかもあるので追々書いていこうと思います。

今後もStorybookを使っていきたいと思っていますが、最近Storybookのコミッター界隈で色々な動きがあったようですね。
これ とか これ
今後、宗派が別れて揉めたり、営利企業の介入によって廃れたりしなければ良いなと思うこの頃です。

We are hiring!

モチベーションクラウドは
「すべての組織を変える」
「世界の経営指標を変える」
事を本気で考え、心からそれを実現したいチームが開発しています。

組織に課題を感じたことのあるエンジニアのかたは少なくないと思います。
もし、少しでもこれらミッションやビジョンに共感したり興味があるというかたは
こちら から是非ご連絡ください!

おまけ

Storybook はフレームワークやアドオンのバージョン違いで動かなくなることがよくあるので、
今回のサンプルを動かした環境の package.json を記しておきます。

package.json
{
  "name": "sfc-story-sample",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "storybook": "start-storybook -p 9001 -c config/storybook"
  },
  "dependencies": {
    "@vue/cli": "^3.2.1",
    "vue": "^2.5.17",
    "vue-class-component": "^6.0.0",
    "vue-property-decorator": "^7.0.0"
  },
  "devDependencies": {
    "@babel/core": "^7.2.2",
    "@storybook/vue": "^4.1.1",
    "@vue/cli-plugin-babel": "^3.2.0",
    "@vue/cli-plugin-typescript": "^3.2.0",
    "@vue/cli-service": "^3.2.0",
    "awesome-typescript-loader": "^5.2.1",
    "babel-loader": "^8.0.4",
    "babel-preset-vue": "^2.0.2",
    "node-sass": "^4.9.0",
    "sass-loader": "^7.0.1",
    "typescript": "^3.0.0",
    "vue-loader": "^15.4.2",
    "vue-template-compiler": "^2.5.21"
  }
}

Viewing all articles
Browse latest Browse all 25

Trending Articles