Tree Shaking とは?
Webpack の仕組みで、パッケージの中で必要なソースコードのみをビルドパッケージに含めて、使わなかったソースコードは除外してくれます。
Vuetify のドキュメントでは、 A-la-carte として説明されてます。
vuetify-loader
Webpack 向けに vuetify-loader
が用意されています。
公式ドキュメントによると、
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 するようになっています。
{
buildModules: [
'@nuxtjs/vuetify'
],
vuetify: {
/* module options */
}
}
nuxt.config.js
に vuetify
という項目が登場して、 new Vuetify({ ... })
で渡すオプションを指定することができます。
最終形の nuxt.config.js
Vuetify の Tree Shaking を使って、 @/components
フォルダ以下のカスタムコンポーネントを自動的に登録させるコードまで含めた最終形がこちらです。
前記事:Nuxt.jsでcomponentsフォルダのVueコンポーネントを自動でimportする
では、 glob
を使ってファイルを探していましたが、遅いので、キャッシュするように変更しています。
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
}
}
}
}
}
}
},
...
}