131
98

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.

Nuxt.jsのbundleサイズを55%削減したwebpack周りの小技

Posted at

Nuxt.jsとLaravelを使って「Devicebook」(https://devicebook.me)というWebサービスを個人開発しています。
今回はNuxt.jsのwebpack周りを改善し、bundleファイルを151kbから67kb(約55%の削減)にした方法をご紹介します。

webpack-bundle-analyzerで分析

Nuxt.jsでは標準でwebpack-bundle-analyzerが組み込まれており、これでbundleされたファイルの中身を分析できます。

nuxt.config.js
build: {
  analyze: true
}

anayzeオプションをtrueにし、Nuxt.jsプロジェクトをビルドしてみましょう。そうすれば以下のような画面が開かれます。

b863486d03c6e960d8444a9b73e670ed.png

この画像が改善前のファイルです。これを参考にしながら削れそうな所を探していきます。

55%の削減ができた3つのポイント

1. lodashのimportを改善する(24kb→5kb)

lodashをimport _ from 'lodash'のように読み込んでしまうと、全てのlodash関数などがbundleされてしまいます。
それを回避するため、使用する関数のみをimportするように変更します。

~/utils/my-util.js
// 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)

例えば以下の様に、デバイスによって表示するコンポーネントを切り替えたい時があります。

MyComponent.vue
<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には非同期コンポーネントという機能があります。
非同期コンポーネントを利用するためには、以下のように修正します。

MyComponent.vue
<script>
export default {
  components: {
    MobileComponent: () => import('./MobileComponent'),
    DesktopComponent: () => import('./DesktopComponent')
  }
}
</script>

こうすることで、MobileComponentとDesktopComponentが一緒にbundleされることはなく、ユーザーは片方のcomponentファイルを読み込みます。

他のよくある改善点

例えばDateTimeライブラリであるmomentはかなりサイズが大きいため、シンプルな時間操作のみを求めているのであればDay.jsという2kbに軽量ライブラリがおすすめです。
またmomentを利用する場合には必要なロケールのみを読み込むなどをして余計なファイルをbundleしないようにしましょう。

それでは、皆さんも良きNuxt.js生活を!

131
98
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
131
98

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?