10
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

NuxtJSがVuetifyのTree Shakingまで面倒を見てくれる

Posted at

Tree Shaking とは?

Webpack の仕組みで、パッケージの中で必要なソースコードのみをビルドパッケージに含めて、使わなかったソースコードは除外してくれます。

Vuetify のドキュメントでは、 A-la-carte として説明されてます。

vuetify-loader

Webpack 向けに vuetify-loader が用意されています。
公式ドキュメントによると、

webpack.config.js
const VuetifyLoaderPlugin = require('vuetify-loader/lib/plugin')

module.exports = {
  plugins: [
    new VuetifyLoaderPlugin()
  ],
}

これで、 vuetify-loader が Tree Shaking してくれるようになります。

@nuxtjs/vuetify

NuxtJS が、 @nuxtjs/vuetify というビルドモジュールを用意してくれています。

@nuxtjs/vuetify には、 vuetify-loader が組み込まれていて、自動的に呼び出して Tree Shaking するようになっています。

nuxt.config.js
{
  buildModules: [
    '@nuxtjs/vuetify'
  ],
  vuetify: {
    /* module options */
  }
}

nuxt.config.jsvuetify という項目が登場して、 new Vuetify({ ... }) で渡すオプションを指定することができます。

最終形の nuxt.config.js

Vuetify の Tree Shaking を使って、 @/components フォルダ以下のカスタムコンポーネントを自動的に登録させるコードまで含めた最終形がこちらです。

前記事:Nuxt.jsでcomponentsフォルダのVueコンポーネントを自動でimportする
では、 glob を使ってファイルを探していましたが、遅いので、キャッシュするように変更しています。

nuxt.config.js
import fs from 'fs'
import path from 'path'
import colors from 'vuetify/es5/util/colors'

const SRC_DIR = 'src'
const COMPONENTS_DIR = 'components'

const srcPath = path.resolve(__dirname, SRC_DIR)
const componentDirs = fs.readdirSync(path.join(srcPath, COMPONENTS_DIR))
const foundComponents = {}

export default {
  srcDir: SRC_DIR,

  ...

  /*
  ** Nuxt.js dev-modules
  */
  buildModules: [
    '@nuxtjs/vuetify'
  ],

  ...

  /*
  ** vuetify module configuration
  ** https://github.com/nuxt-community/vuetify-module
  */
  vuetify: {
    customVariables: [
      '~/assets/variables.sass'
    ],
    theme: {
      options: {
        customProperties: true
      },
      dark: true,
      themes: {
        dark: {
          ...
        }
      }
    },
    treeShake: {
      directives: [
        'Resize'
      ],
      loaderOptions: {
        /**
         * This function will be called for every tag used in each vue component
         * It should return an array, the first element will be inserted into the
         * components array, the second should be a corresponding import
         *
         * originalTag - the tag as it was originally used in the template
         * kebabTag    - the tag normalised to kebab-case
         * camelTag    - the tag normalised to PascalCase
         * path        - a relative path to the current .vue file
         * component   - a parsed representation of the current component
         */
        match (originalTag, { kebabTag, camelTag }) {
          if (kebabTag in foundComponents) {
            return foundComponents[kebabTag]
          }

          const parts = kebabTag.split('-')

          if (parts.length > 1 && componentDirs.includes(parts[0])) {
            for (let i = 1; i < parts.length; i++) {
              const pathPart = parts.slice(0, i)
              const filePart = parts.slice(i)

              const relPath = path.join(COMPONENTS_DIR, ...pathPart, camelTag.substr(-filePart.join('').length))

              const existsJs = fs.existsSync(path.join(srcPath, `${relPath}.js`))
              const existsVue = fs.existsSync(path.join(srcPath, `${relPath}.vue`))

              if (existsJs || existsVue) {
                const ret = [
                  camelTag,
                  `import ${camelTag} from '@/${relPath}'`
                ]

                foundComponents[kebabTag] = ret

                return ret
              }
            }
          }
        }
      }
    }
  },

  ...

}
10
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?