見出し画像

バンドルサイズを減らしてみた

貸し本棚のスタート時はとても小さなサービスだったので全く気にしていなかった問題ですが、時間が経つにつれてみるみるバンドルサイズが肥大化してきました。
地味な作業ですが、その削減について書いておきます。

バンドル(bundle)とは

webpackやviteのようなバンドルツールを使うと、アプリケーションで使用するjavascriptファイルの依存関係を解決して事前読み込みし、単一のjavascriptファイルにまとめてくれます。

貸し本棚は必要なjsファイルのみならず、ルーティングも行っているため、基本的にWebサイトへの初回アクセス時のみUI読み込みが発生します。この初回アクセス時にページが表示されるまで3秒かかるか、5秒かかるか、で初めてアクセスするユーザー様の印象が変わります。

貸し本棚はその構成上、ポータルと各本棚で別々のbundleファイルを読み込んでいます。

貸し本棚のバンドルサイズ

作業開始前は、

  • main.js(ポータル)…4.69MiB

  • sub.js(本棚)…1.7MiB

でした。ポータルは流石にデカイですね。

構成を調べる

バンドルの構成を調べます。

npm i laravel-mix-bundle-analyzer

これをインストールした上で、webpack.mix.jsに

require('laravel-mix-bundle-analyzer');
 if (mix.isWatching()) {
     mix.bundleAnalyzer({
         analyzerPort: 8888,
         analyzerHost: 'kashi-hondana.home'
     });
 }

上記コードを追記します。npm run watchして、kashi-hondana.home:8888にアクセスすると、解析した構成が表示されます。すると、恐ろしいことがわかりました。

見に覚えのないhighlight.jsと殺したはずのmoment.jsが……

この巨大なhighlight.jsはプログラムコードに色を付けるもので、明らかに小説保管サービスには必要ないものです。また、メンテされず非推奨となったmoment.jsは消したはずです。なぜ生き残っているのか。

highlight.jsを調べる

謎のhighlight.jsが何に要求されているかを調べます。

package-lock.jsでhighlight.jsを調べると、diff2htmlがrequireしていました。更にdiff2htmlを調べると、v-code-diffがrequireしています。これは覚えがあります。

版管理の差分表示

貸し本棚には本文の版管理機能があり、現在の本文との差分を表示することができます。その差分ビューアがコードのカラーリングを行うためにhighlight.jsを用いていたようです。

v-code-diffはver.1に上げると正常にimportできなくなったので、代わりにvue-diffを導入します。オプション名が変わる以外は使い方は同じです。デフォルトではハイライト機能が無いので軽量です。

moment.jsを調べる

長い間お世話になったmoment.jsですが、とっくに開発は終了し、非推奨となっていました。どういうわけか公式サイトにはその旨が記載されていません。未だにdeprecatedに気づかず新規プロジェクトに導入してしまう人がいます。私も気づきませんでした。
このmoment.jsはバンドルサイズが大きいという問題があります。localeを読み込むと、日本以外の国のファイルも全部読んでしまいます。

代替として人気があるのはdate-fnsですが、移植に手間を書けたくないのでほぼ互換のday.jsに乗り換えます。極めて怠惰な乗り換え方をしてみます。

import dayjs from 'dayjs';
window.moment = dayjs;
require("dayjs/locale/ja");
moment.locale("ja");
const isSameOrBefore = require('dayjs/plugin/isSameOrBefore');
moment.extend(isSameOrBefore);
const isSameOrAfter = require('dayjs/plugin/isSameOrAfter');
moment.extend(isSameOrAfter);
const relativeTime = require('dayjs/plugin/relativeTime')
moment.extend(relativeTime);

dayjsをmomentにぶち込みます。あとは必要なプラグインを読み込んで終わりです。ほぼ完全互換なのでこれで問題なく動作します。
かっこつけて移行先を間違えると、地球の裏側までgrepする羽目になります。怠惰は美徳です。

この修正は先日実装したものですが、未だにbundleにmoment.jsが残留しています。これもpackage-lock.jsonで調べると、chart.js@2.9.4がrequireしていました。
vue3にアップグレードしたので、chart.jsをver.4にアップグレードします。importでエラーが起きてしまうので、

import Chart from "chart.js/auto";

こんなふうに書き直します。あとはoptions周りが結構変更されていますが、公式ドキュメントのmigrationが丁寧なので読めばわかります。

再構成

余計なものを削除したら、構成とファイルサイズを確認します。

highlight.jsとmoment.jsが消えました

lodashが目立ちますが、これは個別読み込みにするとpredictorが動かなくなる問題が発生したため、今回は見送っています。jQueryはbs4が使うので外せません。

  • main.js(ポータル)…4.69MiB → 3.62MiB

  • sub.js(本棚)…1.7MiB → 1.42MiB

2つ消しただけですが、ポータル側は1MiB以上削減できています。もっと減らしたいですが、今回はこのへんで一回上げてしまいます。


技術的な内容で、知らない人には意味不明、知ってる人には「lodash削れよ」という内容になってしまいましたが、SPA特有の問題に対する地味な作業もやってますよ、という紹介記事でした。


この記事が気に入ったらサポートをしてみませんか?