Nuxt.jsとLaravelを使って「Devicebook」(https://devicebook.me)というWebサービスを個人開発しています。
今回はNuxt.jsのwebpack周りを改善し、bundleファイルを151kbから67kb(約55%の削減)にした方法をご紹介します。
webpack-bundle-analyzerで分析
Nuxt.jsでは標準でwebpack-bundle-analyzerが組み込まれており、これでbundleされたファイルの中身を分析できます。
build: {
analyze: true
}
anayzeオプションをtrueにし、Nuxt.jsプロジェクトをビルドしてみましょう。そうすれば以下のような画面が開かれます。
この画像が改善前のファイルです。これを参考にしながら削れそうな所を探していきます。
55%の削減ができた3つのポイント
1. lodashのimportを改善する(24kb→5kb)
lodashをimport _ from 'lodash'
のように読み込んでしまうと、全てのlodash関数などがbundleされてしまいます。
それを回避するため、使用する関数のみをimportするように変更します。
// import _ from 'lodash'
import escape from 'lodash/escape'
export default function (string) {
// ...
return escape(string)
}
これでbundleされるのはescape関数のみとなります。lodashはgzippedのものでも25kbほどあるため、きちんと気をつけておきましょう。
2. Vuetifyのa-la-carte(110kb→20kb)
VueのマテリアルUIフレームワークといえばVuetify.jsが人気でわたしもお世話になっています。
しかしそのままVue.use(Vuetify)
のようにしてしまうと、Vuetifyの全てのコンポーネントなどがbundleされてしまいます。
そこでa-la-carte(フランス語で、メニューから選んだ/お好みの料理の、などの意味)にimportする必要があります。
詳細はVuetify.jsのドキュメントに書いてあるのでそちらを参照してください。
https://vuetifyjs.com/ja/guides/a-la-carte
3. Vue.jsの Dynamic Import(20kb→5kb)
例えば以下の様に、デバイスによって表示するコンポーネントを切り替えたい時があります。
<template>
<div>
<MobileComponent v-if="$device.isMobile"/>
<DesktopComponent v-else/>
</div>
</template>
<script>
import MobileComponent from './MobileComponent'
import DesktopComponent from './DesktopComponent'
export default {
components: { MobileComponent, DesktopComponent }
}
</script>
この時、スマホのユーザーにはMobileComponentしか表示しませんが、DesktopComponentも一緒にbundleされたjsファイルを読み込んでしまいます。
それを回避するため、Vue.jsには非同期コンポーネントという機能があります。
非同期コンポーネントを利用するためには、以下のように修正します。
<script>
export default {
components: {
MobileComponent: () => import('./MobileComponent'),
DesktopComponent: () => import('./DesktopComponent')
}
}
</script>
こうすることで、MobileComponentとDesktopComponentが一緒にbundleされることはなく、ユーザーは片方のcomponentファイルを読み込みます。
他のよくある改善点
例えばDateTimeライブラリであるmomentはかなりサイズが大きいため、シンプルな時間操作のみを求めているのであればDay.jsという2kbに軽量ライブラリがおすすめです。
またmomentを利用する場合には必要なロケールのみを読み込むなどをして余計なファイルをbundleしないようにしましょう。
それでは、皆さんも良きNuxt.js生活を!