Madogiwa Blog

主に技術系の学習メモに使っていきます。

Vue3系×Webpack5系の環境にStorybookを導入するMEMO📝

以下のような環境にStorybookを導入してみたので対応したこととかをメモしておきます。

package version
vue 3.1.4
webpack 5.44.0

Storybookとは

まずはStorybookについて簡単に説明します。

storybook.js.org

Storybook is an open source tool for building UI components and pages in isolation. It streamlines UI development, testing, and documentation.

上記の通りUIコンポーネントの開発ツールです、以下のような形でコンポーネントのサンプルを閲覧したり、私がVueを使っているのですが、propsをGUI上で設定して動作確認が行えたりします。

f:id:madogiwa0124:20210717163859p:plain

Storybookを導入する

今回はStorybookをVue3、Webpack5の環境に導入する前提で導入方法をメモしていきます。

Storybookのinstall

まずは以下のコマンドを実行してWebpack5用のStorybookをinstallします。

$ npx sb init --builder webpack5

上記コマンドを実行すると以下のようなことが実行されます。

  • Storybook関連ライブラリのインストール
  • Storybook用の設定ファイル群の生成
  • サンプルファイルの生成

Vue3を使用していたので特別な設定が必要かなと思ったのですが、init時に自動的に判断してVue3用の設定をしてくれるようです、便利✨

既存のWebpackと設定をあわせる

実際に自身でWebpackの環境をすでに用意している場合にはalias等の設定をStorybook用のWebpackと合わせておかないとmoduleの解決ができないので.storybook/webpack.config.jsを用意して上げて修正します。

const path = require("path");
const rootPath = path.resolve(__dirname, "../");

module.exports = ({ config }) => {
  config.resolve.alias["@"] = rootPath;
  config.resolve.alias["~"] = rootPath;
  config.resolve.alias["@js"] = `${rootPath}/app/javascript`;
  config.resolve.alias["@css"] = `${rootPath}/app/javascript/stylesheets`;
  config.resolve.alias["@spec"] = `${rootPath}/spec/javascript`;
  config.resolve.alias["querystring"] = "querystring-es3";
  config.resolve.alias["process"] = "process/browser";

  config.module.rules.push({
    test: /\.(scss|css)/,
    use: ["style-loader", "css-loader", "sass-loader"],
  });

  return config;
};

私の場合はaliasの設定に加えて、VueのSFCのstyle内のでimportが失敗してたのでcssまわりの設定も既存のWebpackから移植しました。

tacamy.hatenablog.com

グローバルで読み込ませたいファイルのimport

またcssフレームワーク等は、グローバルに読み込ませたかったのでpreview.jsでimportするようにしました。

// 全体に適用するCSSをimport
import "@js/stylesheets/application.scss";

export const parameters = {
  actions: { argTypesRegex: "^on[A-Z].*" },
  controls: {
    matchers: {
      color: /(background|color)$/i,
      date: /Date$/,
    },
  },
};

qiita.com

Storyを配置するディレクトリを設定

.storybook/main.jsstoriesに自分がStoryを配置したいディレクトリパスを設定してあげます。

module.exports = {
  stories: ["../app/javascript/components/**/*.stories.@(js|jsx|ts|tsx)"],
  addons: ["@storybook/addon-links", "@storybook/addon-essentials"],
  core: {
    builder: "webpack5",
  },
};

Storyを追加する

あとは以下のような感じで任意のコンポーネントのStoryを追加してあげればOKです🎉

import FeedCard from "@js/components/feed/FeedCard.vue";
import { buildFeed } from "@spec/mocks/Feed";

export default {
  title: "FeedCard",
  component: FeedCard,
};

const Template = (args) => ({
  components: { FeedCard },
  setup() {
    return { args };
  },
  template: '<feed-card  v-bind="args" />',
});

const feed = buildFeed(1);
feed.lastEntry.eyeCatchingImage = "";

export const Default = Template.bind({});
Default.args = {
  feed: feed,
};

この辺の記載方法は以下を参照してください📚

storybook.js.org

MEMO

以下はメモ

node_modules配下のTypeScriptの型チェックで落ちる

なぜか、node_modules配下のTypeScriptの型チェックで落ちるようになったので、

node_modules/@vue/runtime-dom/dist/runtime-dom.d.ts:1430:15 - error TS2320: Interface 'IntrinsicAttributes' cannot simultaneously extend types 'ReservedProps' and 'Attributes'.
  Named property 'key' of types 'ReservedProps' and 'Attributes' are not identical.

以下のようにskipLibCheckをtrueにしました。

"skipLibCheck": true

stackoverflow.com

おわりに

Storybook今まで使ったことがなかったのですが、GUIでpropsをいじって動作確認出来たり、マージンのpx等も確認出来たりと動作確認に便利ですね!

また静的に出力もできるのでgithub pagesとかにhostingしてコンポーネント設計のドキュメントとしてそのまま利用できそうなところも、良さそう・・・!