【Nuxtjs】パフォーマンス改善した件 - fontawesome、date-fnsのimport周りチューニング

5 min読了の目安(約5100字TECH技術記事

背景

業務上でフロントの速度改善をやることになり、lighthouseのパフォーマンススコアをだいぶ改善されたのでやったことや知見をシェアしたいと思います。

改善前のパフォーマンススコア

問題点を探す

速度改善にあたって、まずやることは問題点を分析することです。lighthouseの計測結果ではJSのパースに時間かかるとのことで、まずdev toolのnetworkタブからJSのサイズを確認してみることにしました。

app.jsのサイズは408kbでかなり重いので、まずapp.jsのサイズを削減することからチューニングすることに決めました。

分析

app.jsの中身を分析するためbundle analyzerを使いました。使い方はターミナルに下記コマンドを叩いたら分析のレポートを表示されます。

yarn nuxt build --analyze

分析の結果は下記です。

app.jsのサイズは2.11MBでした。

.nuxtは約1.34MBでした。

ということで.nuxtはほぼapp.jsの半分以上を占めてるのがわかります。さらにここから掘り下げていきます。

bundle analyzerのデフォルトでは.nuxtの中身を更に細かくみることができません。中身を見るためにまず下記の設定にチェックを入れてください。

Show content of concatenated modulesにチェックを入れれば.nuxtの中身を更に細かく見れます。

fontawesomeが.nuxtの中に入ってることを確認できます。

fontawesomeの容量を見るとほぼ700kbでした。

そしてもう一つサイズが大きいのはdate-fnsです、約520kbでした。

ということで今回は

  • fontawesome

  • date-fns

この2つを中心にチューニングします。

チューニング - fontawesome

fontawesomeは下記ファイルでアイコンをインポートしていた。

// plugins/font-awesome.js

import Vue from 'vue';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import { config, library } from '@fortawesome/fontawesome-svg-core';
import * as fontsSolid from '@fortawesome/free-solid-svg-icons';

const {
  ...icons
} = { ...fontsSolid };

// 利用するアイコンをlibraryに追加
Object.values(icons).forEach((icon) => library.add(icon));

// グローバルコンポーネントに登録
Vue.component('fa', FontAwesomeIcon);

上記のコードでわかったのは、アイコンは全部importされてます。

// これです。
import * as fontsSolid from '@fortawesome/free-solid-svg-icons';

全部importされてることでサイズが大きくなるから、必要なアイコンを洗い出して、それだけimportします。

上記のimportを書きみたいに書き替えます。

// アイコンをdeep importすることでバンドル後のapp.jsのサイズを減らせる
import { faHome } from '@fortawesome/free-solid-svg-icons/faHome';
import { faChevronRight } from '@fortawesome/free-solid-svg-icons/faChevronRight';
import { faStar } from '@fortawesome/free-solid-svg-icons/faStar';
import { faAngleRight } from '@fortawesome/free-solid-svg-icons/faAngleRight';
import { faClock } from '@fortawesome/free-solid-svg-icons/faClock';
import { faTag } from '@fortawesome/free-solid-svg-icons/faTag';
import { faSearch } from '@fortawesome/free-solid-svg-icons/faSearch';
import { faTrain } from '@fortawesome/free-solid-svg-icons/faTrain';
import { faMapMarkerAlt } from '@fortawesome/free-solid-svg-icons/faMapMarkerAlt';
import { faCaretDown } from '@fortawesome/free-solid-svg-icons/faCaretDown';

// 利用するアイコンを配列に追加
const solidIcons = {
  faHome,
  faAngleRight,
  faChevronRight,
  faStar,
  faClock,
  faTag,
  faSearch,
  faTrain,
  faMapMarkerAlt,
  faCaretDown,
};
// 利用するアイコンをlibraryに追加
Object.values(solidIcons).forEach((icon) => library.add(icon));

// グローバルコンポーネントに登録
Vue.component('fa', FontAwesomeIcon);

修正後に再度bundle analyzerで分析すると結果はこうなります。

.nuxtは1.34MBから682kbまで抑えました。

fontawesomeのアイコンも約8kbまで抑えました。

チューニング - date-fns

まずは改善前のdate-fnsのサイズをもう一度確認します。

date-fnsは約520kbを占めてます。

date-fnsはnuxt.config.jsの設定でimportされます。

buildModules: [
    ['@nuxtjs/date-fns', { locales: ['ja'] }]
  ],

上記の書き方ですとdate-fnsのメソッドを全部imortされちゃいます。

なので解決法としては必要なメソッドを洗い出し、それだけimportします。

現状formatメソッドしか使ってないから、今回はそれだけ指定しました。

['@nuxtjs/date-fns', { locales: ['ja'], methods: ['format'] }],

上記の修正後に再度分析してみると

date-fnsは96kbまで抑えました。

.nuxt最初の1.34MBから260kbまで削減できました。

最後にもう一度app.jsのサイズはどうなるのか確認します。

app.jsは最初の2.11MBから1.03MBまで半分くらい抑えました。

最後に改善後のlighthouseのスコアを見てみます。

改善後にnetworkからapp.jsも確認します。

結論

  • 必要なアイコンだけimportすることが重要

  • 使ってるライブラリがあれば、必要なメソッドだけimportすることが重要

最後まで読んでくださってありがとうございました!
それではまた。

参考リンク

fontawesomeのアイコンを個別にimportについて

date-fnsのメソッドをimportについて