Vuetify + Nuxt.js + @mdi/js で最小限のアイコンをバンドルする

2 min read読了の目安(約2400字

執筆中ですが、ヒントになればと思い公開しています。

概要

Nuxt SSR + Vuetify の構成でロードがおそすぎる状況を改善するための一つの手段として、Material Design Icon の読み込みを、Vuetify 公式を参考に導入してみたが、
わかりにくいところがあったので備忘録も兼ねて記述します。

基本的な使い方の補足

基本的な使い方は公式の以下を参照のこと。

Icon Fonts — Vuetify

@mdi/js のインストールは公式のまま実行

その後の追記する記述が Nuxt の場合少し違う。

まず、 src/plugins/vuetify.js は作成する必要はなく、
代わりに nuxt.config.jsbuildModules にて、
'@nuxtjs/vuetify' のオプションとして以下を追加する。

  buildModules: [
    // https://go.nuxtjs.dev/vuetify
    [
      '@nuxtjs/vuetify',
      {
        customVariables: ['~/assets/scss/vuetify/variables/_index.scss'],
        optionsPath: '~/configs/vuetify.js',
        treeShake: true,
        defaultAssets: {
          font: {
            family: 'Noto Sans JP',
          },
          icons: 'mdiSvg', // ← ここを追加
        },
      },
    ],
    ・・・
  ]

公式の src/plugins/vuetify.js の記述例では、

export default new Vuetify({
  icons: {
    iconfont: 'mdiSvg',
  },
})

↑このように書かれているので、初め nuxt.config.js にも icons: { 省略 } と記述されていた。

しかし、@nuxt.js/vuetifyREADME を読むと、
icons オプションは Vuetifyicons.iconfont をオーバライドすると書いてあったので、先述のように変更するとうまく行った。

Image from Gyazo

nuxt-community/vuetify-module: Vuetify Module for Nuxt.js

また、上記ドキュメントのテーブルには icons に指定できる値として、 mdiSvg はないが、
それはおそらくデフォルトではないということだと思う。

@mdi/js をインストールしていれば、先述のように指定できる。

重要: ここまでで Vuetify が必要とするデフォルトのアイコンは読み込まれる

Vuetify のデフォルトのコンポーネントで使用されているアイコンたち。
例えば、v-expansion-panel のキャレット(シェブロン)や v-navigation-drawer のハンバーガーアイコンなど。

どのアイコンがデフォルトで読み込まれるかは以下の Vuetify のソースコードを確認のこと

vuetify/mdi-svg.ts at master · vuetifyjs/vuetify

なので、Vuetify デフォルトのアイコンに対してわざわざ slot を使ったりして、
個別で読み込んだアイコンを差し込んで上げる必要はない。

それ以外に自分で v-icon などでアイコンを使う部分に関しては、個別に import が必要

その方法は、以下のように公式どおりです。

<!-- Vue Component -->

<template>
  <v-icon>{{ svgPath }}</v-icon>
</template>

<script>
  import { mdiAccount } from '@mdi/js'

  export default {
    data: () => ({
      svgPath: mdiAccount
    }),
  }
</script>

Icon Fonts — Vuetify

アイコンが多い場合個別に読み込むのが非常にめんどくさいのでその解消方法

以下執筆中