Nuxt.jsとStorybook(5.3以降)の両方でFont Awesomeを使えるようにする


少し格闘した結果、Nuxt.jsのアプリとStorybookの両方でFont Awesomeを使ったコンポーネントを表示できるようにできました😤

こんな感じに…

構成

簡単なNuxt.js + Storybookの構成にしています。

.
├── .storybook
│   ├── main.js
│   └── preview.js
│   
├── components
│   ├── Component.vue
│   └── index.stories.js
│
├── nuxt.config.js
├── package.json

また、Font Awesomeのアイコンは次の方針で読み込みます。

  • production(Nuxt.js)側: 少しでも容量を軽くするために 必要なフォントのみを読み込む
  • development(Storybook)側: フォントを指定する手間を省くため すべての使用可能なフォントを読み込む

Storybook 5.3からは設定ファイルが main.js に変わる

使った環境はStorybook 5.3以降と 設定ファイルの構造が新しくなった ものになります。

package.json(抜粋)
...
  "dependencies": {
    "nuxt": "^2.0.0"
  },
  "devDependencies": {
    "@storybook/vue": "^5.3.17"
  }
...

Storybook 5.3からは config.jsmain.js に変わり、storyを表示する部分に関わる設定は preview.js(下の図にないが) として新設されます。


引用: https://medium.com/storybookjs/declarative-storybook-configuration-49912f77b78

従来の方法も使えますが、Storybook 6系になるまでは移行を考えておきましょう。

The old config.js syntax and configurable hierarchy separators will be supported until Storybook version 6.0.

ここでは新しくなった main.js については詳しく解説しません。

npmパッケージを導入する

はじめに、FontAwesomeを使用可能にするパッケージを導入します。

yarn add nuxt-fontawesome \
@fortawesome/fontawesome-svg-core \
@fortawesome/vue-fontawesome \
@fortawesome/free-solid-svg-icons \
@fortawesome/free-regular-svg-icons \
@fortawesome/free-brands-svg-icons 

Nuxt.js 用の設定

こちらは、少しでも容量を軽くするために使うアイコンだけを読み込みます。
アイコンの指定は、 fas でも fab でも fa + アイコン名のキャメルケース となります。

./nuxt.config.js
  modules: [
    'nuxt-fontawesome',

...

  fontawesome: {
    imports: [
      {
        set: '@fortawesome/free-brands-svg-icons',
        icons: ['faVuejs']
      },
      {
        set: '@fortawesome/free-solid-svg-icons',
        icons: ['faTimesCircle']
      }
    ]
  },

Storybook用の設定

こちらは Font Awesomeのアイコンをすべて読み込みます。

main.js はStorybookで表示したいstoryの場所を指定します。

.storybook/main.js
module.exports = {
  stories: ['../components/**/*.stories.js'],
...

preview.js でFont Awesomeをすべてのstoryに読み込みます。
configure のパスは main.js で指定したパスとつじつまが合うようにします。

.storybook/preview.js
import { configure } from '@storybook/vue'
import Vue from 'vue'

import { library } from '@fortawesome/fontawesome-svg-core'
import { fas } from '@fortawesome/free-solid-svg-icons'
import { fab } from '@fortawesome/free-brands-svg-icons'
import { far } from '@fortawesome/free-regular-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
library.add(fas, far, fab)

Vue.component('font-awesome-icon', FontAwesomeIcon)
configure(require.context('../components', true, /\.stories\.js$/), module)

Nuxtコンポーネント

この設定により、コンポーネント側では FontAwesomeIcon コンポーネントを呼び出すだけでNuxt.jsとStorybookで同一のアイコンが表示されます。

各コンポーネント、 *.stories.js にFont Awesomeをimportするコードを書く必要がなくなります✌️

./components/Component.vue
<template>
  <div>
    <font-awesome-icon :icon="['fab', 'vuejs']"/>
  </div>
</template>

参考

Declarative Storybook configuration - Storybook - Medium
https://medium.com/storybookjs/declarative-storybook-configuration-49912f77b78

FortAwesome/vue-fontawesome: Font Awesome 5 Vue component
https://github.com/FortAwesome/vue-fontawesome

Font awesome を Vue.js で使ってみよう - Qiita
https://qiita.com/kurararara/items/d76776a7dc2d763a068b