chibi929's blog

その一歩先へ。ちびです!猫の名前です!ドラゴンボール好き!純粋なサイヤ人のように生きたいと思っています!IT技術で少しでも多くの人が笑顔になってくれたらいいなと。

Nuxt.js x Class API x Storybook (x SCSS)

前提・環境

$ node -v
v14.17.3

$ npm -v
7.19.1

$ yarn -v
1.22.10

$ nuxt -v
@nuxt/cli v2.15.8
  • Nuxt.js x TypeScript x Class API のプロジェクトが用意されていること

Class API の Nuxt.js で Storybook を使ってみる

まずはデフォルトで動作確認

1. まずは https://storybook.js.org/docs/react/get-started/install に従って Storybook をインストール

$ npx sb init

2. デフォルト状態で動作確認

$ yarn storybook

3. 問題ないことを確認

f:id:chibi929:20211001055526p:plain
Storybook (Default)

まぁ。。。Options API の例だし、できるよね。

続いて、↑ で生成された Vue ファイルを Class API 向けに編集する

1. 編集作業

// ./stories/Button.vue

  <template>
    <button type="button" :class="classes" @click="onClick" :style="style">{{ label }}</button>
  </template>

- <script>
- import './button.css';
+ <script lang="ts">
+ import { Vue, Component, Prop } from 'vue-property-decorator'

- export default {
-   name: 'my-button',
+ @Component
+ export default class Input extends Vue {

-   props: {
-     label: {
-       type: String,
-       required: true,
-     },
-     primary: {
-       type: Boolean,
-       default: false,
-     },
-     size: {
-       type: String,
-       default: 'medium',
-       validator: function (value) {
-         return ['small', 'medium', 'large'].indexOf(value) !== -1;
-       },
-     },
-     backgroundColor: {
-       type: String,
-     },
-   },
+   @Prop({ type: String, required: true })
+   private readonly label!: string
+   @Prop({ type: Boolean, default: false })
+   private readonly primary!: boolean
+   @Prop({
+     type: String,
+     default: 'medium',
+     validator: (value) => {
+       return ['small', 'medium', 'large'].indexOf(value) !== -1
+     },
+   })
+   private readonly size!: string
+   @Prop({ type: String })
+   private readonly backgroundColor!: string

-   computed: {
-     classes() {
-       return {
-         'storybook-button': true,
-         'storybook-button--primary': this.primary,
-         'storybook-button--secondary': !this.primary,
-         [`storybook-button--${this.size}`]: true,
-       };
-     },
-     style() {
-       return {
-         backgroundColor: this.backgroundColor,
-       };
-     },
-   },
+   private get classes() {
+     return {
+       'storybook-button': true,
+       'storybook-button--primary': this.primary,
+       'storybook-button--secondary': !this.primary,
+       [`storybook-button--${this.size}`]: true,
+     }
+   }
+   private get style() {
+     return {
+       backgroundColor: this.backgroundColor,
+     }
+   }

-   methods: {
-     onClick() {
-       this.$emit('onClick');
-     },
-   },
+   private onClick() {
+     this.$emit('onClick')
+   }
- };
+ }
    </script>

+ <style scoped>
+ .storybook-button {
+   font-family: 'Nunito Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
+   font-weight: 700;
+   border: 0;
+   border-radius: 3em;
+   cursor: pointer;
+   display: inline-block;
+   line-height: 1;
+ }
+ .storybook-button--primary {
+   color: white;
+   background-color: #1ea7fd;
+ }
+ .storybook-button--secondary {
+   color: #333;
+   background-color: transparent;
+   box-shadow: rgba(0, 0, 0, 0.15) 0px 0px 0px 1px inset;
+ }
+ .storybook-button--small {
+   font-size: 12px;
+   padding: 10px 16px;
+ }
+ .storybook-button--medium {
+   font-size: 14px;
+   padding: 11px 20px;
+ }
+ .storybook-button--large {
+   font-size: 16px;
+   padding: 12px 24px;
+ }
+ </style>

2. そして動作確認!

$ yarn storybook

問題なく行ける!!

この調子で SCSS もやってしまえ!

Style を SCSS にする

1. 編集作業

// ./stories/Button.vue

- <style scoped>
+ <style lang="scss" scoped>

2. 動作確認

$ yarn storybook
ERROR in ./stories/Button.vue?vue&type=style&index=0&id=43fc969c&lang=scss&scoped=true& (./node_modules/vue-docgen-loader/lib??ref--12!./node_modules/vue-loader/lib??vue-loader-options!./stories/Button.vue?vue&type=style&index=0&id=43fc969c&lang=scss&scoped=true&) 49:0
Module parse failed: Unexpected token (49:0)
File was processed with these loaders:
* ./node_modules/vue-docgen-loader/lib/index.js
* ./node_modules/vue-docgen-loader/lib/index.js
* ./node_modules/vue-loader/lib/index.js
You may need an additional loader to handle the result of these loaders.
  • ここに来て、エラー!

3. ということでググる

ということでいじる

// ./.storybook/main.jsmain.js

+ const path = require('path');

module.exports = {
    "stories": [
    "../stories/**/*.stories.mdx",
    "../stories/**/*.stories.@(js|jsx|ts|tsx)"
    ],
    "addons": [
    "@storybook/addon-links",
    "@storybook/addon-essentials"
-   ]
+   ],
+   webpackFinal: async (config, { configType }) => {
+     // `configType` has a value of 'DEVELOPMENT' or 'PRODUCTION'
+     // You can change the configuration based on that.
+     // 'PRODUCTION' is used when building the static version of storybook.
+ 
+     // Make whatever fine-grained changes you need
+     config.module.rules.push({
+       test: /\.scss$/,
+       use: ['style-loader', 'css-loader', 'sass-loader'],
+       include: path.resolve(__dirname, '../'),
+     });
+ 
+     // Return the altered config
+     return config;
+   },
}

4. 動作確認

$ yarn storybook

いけた!

assets/scss/styles.scss に定義してある変数を使ってみる

1. Vue ファイルの編集作業

// ./stories/Button.vue

  .storybook-button--primary {
-   color: white;
-   background-color: #1ea7fd;
+   color: $color_light;
+   background-color: $color_primary;
  }

2. 動作確認

$ yarn storybook
ERROR in ./stories/Button.vue?vue&type=style&index=0&id=43fc969c&lang=scss&scoped=true& (./node_modules/css-loader/dist/cjs.js!./node_modules/vue-loader/lib/loaders/stylePostLoader.js!./node_modules/sass-loader/dist/cjs.js!./node_modules/vue-loader/lib??vue-loader-options!./stories/Button.vue?vue&type=style&index=0&id=43fc969c&lang=scss&scoped=true&)
Module build failed (from ./node_modules/sass-loader/dist/cjs.js):
SassError: Undefined variable.
╷
59 │   color: $color_light;
│          ^^^^^^^^^^^^

3. Storybook の設定周り編集作業

// ./.storybook/main.js

    config.module.rules.push({
    test: /\.scss$/,
-   use: ['style-loader', 'css-loader', 'sass-loader'],
+   use: [
+     'style-loader',
+     'css-loader',
+     'sass-loader',
+     {
+       loader: 'sass-resources-loader',
+       options: {
+         resources: ['assets/scss/styles.scss'],
+       },
+     },
+   ],
    include: path.resolve(__dirname, '../'),
    })

4. 動作確認

$ yarn storybook

f:id:chibi929:20211001064622p:plain
Storybook (頑張ったやつ)

最後に

  • Storybook をインストールしたことで、 yarn dev 実行時に CSS-Loader 周りにエラーが出る
  • yarn add -D css-loader@4.2.0 とバージョン指定することで解決できる

yarn devyarn storybook 別々のビルドになるので、両方確認しなきゃいけないことがわかった。