Open11

Inertia.js + tailwindCSS + Vue3 に Storybookを導入する

wadakatuwadakatu

お決まりのコマンドでStorybookのセットアップ
結構時間かかる(2~3分)

npx sb init
wadakatuwadakatu

ありえないくらいhas unmet peer dependencyのWarningが出るが一旦放置
https://github.com/storybookjs/storybook/issues/11492
↑なぜかCloseされているが、まだ解決してない模様

warning "@storybook/addon-actions > @storybook/addons@6.5.15" has unmet peer dependency "react@^16.8.0 || ^17.0.0 || ^18.0.0".
warning "@storybook/addon-actions > @storybook/addons@6.5.15" has unmet peer dependency "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0".
warning "@storybook/addon-actions > @storybook/api@6.5.15" has unmet peer dependency "react@^16.8.0 || ^17.0.0 || ^18.0.0".
.
. 【中略】
.
warning "@storybook/manager-webpack5 > @storybook/core-client@6.5.15" has unmet peer dependency "react@^16.8.0 || ^17.0.0 || ^18.0.0".
warning "@storybook/manager-webpack5 > @storybook/core-client@6.5.15" has unmet peer dependency "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0".
warning "@storybook/manager-webpack5 > @storybook/ui@6.5.15" has unmet peer dependency "react@^16.8.0 || ^17.0.0 || ^18.0.0".
warning "@storybook/manager-webpack5 > @storybook/ui@6.5.15" has unmet peer dependency "react-dom@^16.8.0 || ^17.0.0 || ^18.0.0".
warning "@storybook/vue3 > vue-docgen-loader > jscodeshift@0.13.1" has unmet peer dependency "@babel/preset-env@^7.1.6".
wadakatuwadakatu

Storybook用のESLintプラグインを入れるかどうか
eslint使っているので、yesを選択

✔ Do you want to run the 'eslintPlugin' migration on your project? … yes

ESLintの設定ファイルにプラグインを追加

eslintrc.yml
extends:
  - 'plugin:vue/vue3-essential'
  - 'eslint:recommended'
  - '@vue/typescript/recommended'
+ - 'plugin:storybook/recommended'
  - 'prettier'
wadakatuwadakatu

諸々のインストールが終わったら以下コマンドでStorybookを起動

yarn storybook
wadakatuwadakatu

Storybookは、デフォルトでPostCSS7を利用する
しかし、tailwindcssはPostCSS8で動いているので、PostCSS8を利用するように別途設定する必要がある

まずは、Addonを1つインストール

https://storybook.js.org/addons/@storybook/addon-postcss

yarn add -D @storybook/addon-postcss

.storybook/main.jsに追加したAddonを追記

main.js
addons: [
    '@storybook/addon-links',
    '@storybook/addon-essentials',
    '@storybook/addon-interactions',
+   {
+     name: '@storybook/addon-postcss',
+     options: {
+       postcssLoaderOptions: {
+         implementation: require('postcss'),
+       },
+     },
+. },
  ],

.storybook/preview.jsにtailwindCSSのファイルパスをimport

preivew.js
+ import '../resources/css/app.css';
wadakatuwadakatu

inertia.jsでは、propsを取得するのにusePage()関数を使う
usePageはReadonlyなので、直接モック関数に書き換えるのはベストではない。
しかし、@ts-ignoreを使うと一応動くのでこれで行く

もし、他の良い方法あれば教えてください。

import * as InertiaVue from '@inertiajs/inertia-vue3';

setup() {
    // @ts-ignore
    InertiaVue.usePage = jest.fn().mockImplementationOnce(() => {
      return args;
    });
    return { args };
},
wadakatuwadakatu

ziggy.jsを使っているので、window.route関数のモックを用意する必要がある

エラー内容

Uncaught TypeError: window.route is not a function

モック化

index.stories.ts
import { jest } from '@storybook/jest';

declare global {
  var route: typeof jest.mocked;
}

// has(), current()関数も必要なのでモックする
 window.route = jest.fn().mockImplementation(() => {
      return {
        has: jest.fn(),
        current: jest.fn().mockImplementation(() => {
          return 'my-course';
        }),
      };
});
wadakatuwadakatu

SCSSを使っているコンポーネントのStoryを作ろうとしたら下記のエラーが出た

ModuleParseError: Module parse failed: Unexpected token (2:43)
File was processed with these loaders:
 * ./node_modules/@storybook/vue3/node_modules/vue-docgen-loader/lib/index.js
 * ./node_modules/@storybook/vue3/node_modules/vue-docgen-loader/lib/index.js
 * ./node_modules/@storybook/vue3/node_modules/vue-loader/dist/index.js
You may need an additional loader to handle the result of these loaders.
.
.
中略
.
.
WARN Broken build, fix the error above.
WARN You may need to refresh the browser.

解決策

.storybook/main.jsに下記の記述が必要

.storybook/main.js
+const path = require('path');

module.exports = {
  stories: ['../stories/**/*.stories.mdx', '../stories/**/*.stories.@(js|jsx|ts|tsx)'],
  addons: [
    '@storybook/addon-links',
    '@storybook/addon-essentials',
    '@storybook/addon-interactions',
    {
      name: '@storybook/addon-postcss',
      options: {
        postcssLoaderOptions: {
          implementation: require('postcss'),
        },
      },
    },
  ],
  framework: '@storybook/vue3',
  core: {
    builder: '@storybook/builder-webpack5',
  },
+ webpackFinal: async (config) => {
+  config.module.rules.push({
+    test: /\.scss$/,
+    use: ['style-loader', 'css-loader', 'sass-loader'],
+    include: path.resolve(__dirname, '../'),
+  });
+  return config;
+ },
};

参考資料

https://stackoverflow.com/questions/60704093/using-storybook-vue-with-scss

wadakatuwadakatu

Ziggy-jsのroute関数を使っているコンポーネントのStory内で以下のエラーに遭遇

<!-- 例 -->
<Button :href="route('top')" primary quick>コース詳細</Button>
_ctx.route is not a function

以下の記述をpreview.jsに追加することで解決

import { app } from '@storybook/vue3';

const route = (route) => {
  return '#';
};
app.mixin({ methods: { route } });