ブラウザ向けのJavaScriptだとファイルサイズはある程度気になると思います。
この記事では、ファイルサイズの計測方法やボトルネックとなってるライブラリの見つけ方についてできるだけ簡単な方法をまとめます。
ファイルサイズ
ファイルサイズと一言にいっても、ブラウザでは大体minifyしてから配布するのでminify後のファイルサイズも重要です。
- ソースコード自体のファイルサイズ
- minifyしたファイルサイズ
- minify + gzipしたファイルサイズ
コメントの多いソースコードはminifyするとかなり小さくなったりすることが多いので、ソースコード自体のファイルサイズでは比較しにくいです。
また、ソースコードにおいて assert
モジュールを使っているとファイルサイズが10kb弱程度minify後で変わります。
assert
モジュールは通常外しても問題ないので、unassertでビルド時に取り除きます。
色々ライブラリを使っているプロジェクトだとunassertするだけで5%程度ファイルサイズが減りました。
何がいいたいかというとminifyやビルドの方法でもサイズが異なります。
そのため、プロジェクトにおいてのファイルサイズは計測が結構面倒くさいという話を後半します。
minify後のファイルサイズを取得
minify後のファイルを得るにはbundle-sizeというツールを使うのが簡単です。
bundle-sizeでは指定したパッケージやentry pointをminifyしたファイルサイズを環境変数毎に一覧できます。
# bundle-size lib/index.js みたいなentry pointもいける
❯ bundle-size almin -e development -e production
almin@0.9.0
env bundle minify gzip
-- 116 kB 60.5 kB 16.6 kB
development 116 kB 60.5 kB 16.6 kB
production 116 kB 60.5 kB 16.6 kB
bundle-sizeはbundle後のファイルサイズのみで、依存ツリーを見ることはできません。(いまのところ)
一方、package-size-analyzerを使うと、パッケージや指定したentry pointでビルドした結果の依存ツリーを見ることができます。(逆にこちらはminifyした結果が見られない)
# -e でentry point 、 -j でstats.json
❯ package-size-analyzer -p almin
__ROOT__: 111.46 KB
<self>: 17 B
almin: 57.81 KB
<self>: 55.86 KB
object-assign: 1.95 KB
<self>: 1.95 KB
package-size-analyzer: 5.17 KB
<self>: 0 B
process: 5.17 KB
<self>: 5.17 KB
assert: 11.43 KB
<self>: 11.43 KB
util: 15.4 KB
<self>: 15.4 KB
inherits: 672 B
<self>: 672 B
events: 8 KB
<self>: 8 KB
lru-map-like: 7.84 KB
<self>: 7.84 KB
map-like: 5.13 KB
<self>: 5.13 KB
ファイルサイズは本家だと単位付けてくれないので、PRを出しています。
(READMEもなくてアレなので、forkするかもしれないです)
bundle-sizeはBrowserifyを内部的に使いますが、package-size-analyzerは内部的にwebpackを使っています。
これらは、どちらかというライブラリのサイズを分析する向けとなっています。
実際のプロジェクトだと複雑なビルドが絡まっていたりするため、設定なしで使えるツールには限界がありそうです。
プロジェクトのライブラリ依存ツリーを見る
プロジェクトでは色々なライブラリを使うので、無駄にファイルサイズの大きいものがうっかり混ざっている事があります。dedupeされてないとかで二重に入ってしまうなどもありえます。
そういう場合は実際にbundleしているツールを使って、その結果から分析してみると分かりやすいです。
Browserifyを使っているプロジェクトで依存ツリーを見る
Browserifyで依存ツリーをみるにはdiscを使うのが簡単です。
$(npm bin)/browserify --full-paths src/index.js | discify --open
で依存ツリーを可視化して見ることができます。
webpackを使っているプロジェクトで依存ツリーを見る
webpackはプロジェクトの依存ツリーを分析するためのファイルをJSONで入手できます。
具体的に依存してるモジュールでどれが大きいのかを調べるには、webpackのstats.jsonを使った方法が分かりやすいです。
webpackでは--json
でbundleしたモジュールの解析結果をJSONとして取得できます。
$(npm bin)/webpack --json --profile > stats.json
この結果取得できる stats.json
を以下のツールなどに投げて見ると依存ツリーを可視化してみることができます。
詳しくはSurviveJS - Analyzing Build Statisticsを見ると良いです。
毎回jsonを吐いて、ブラウザで見るのは大変なのでコマンドラインで依存ツリーを見る方法としてwebpack-bundle-size-analyzerを使う方法が有名です。
次のようにパイプでstats.json
として吐いていたものを渡すだけで依存ツリーのファイルサイズを出してくれます。(ただしminify前のソースコードとしてのサイズです)
❯ $(npm bin)/webpack -p --json | webpack-bundle-size-analyzer
react: 581.8 KB (78.8%)
almin: 57.81 KB (7.83%)
object-assign: 1.95 KB (3.37%)
<self>: 55.86 KB (96.6%)
fbjs: 32.32 KB (4.38%)
util: 15.4 KB (2.09%)
assert: 11.43 KB (1.55%)
events: 8 KB (1.08%)
lru-map-like: 7.84 KB (1.06%)
map-like: 5.13 KB (0.695%)
process: 2.01 KB (0.272%)
object-assign: 896 B (0.119%)
inherits: 672 B (0.0889%)
react-dom: 63 B (0.00833%)
<self>: 14.85 KB (2.01%)
おわりに
webpack-bundle-size-analyzerのリポジトリにも書いてありますが、webpackのstats.jsonを使った方法は、minify後ではなくminify前のファイルサイズが表示されます。
Consequently the stats shown by webpack-bundle-size-analyzer will report sizes before minification. This should still give a pretty good idea of what contributes to your bundle size but some libraries will compress better than others, so they can be misleading.
-- webpack-bundle-size-analyzer
そのため、minify後のファイルサイズと依存ツリーを得る方法が今のところよく分かっていません。(stats.json自体にも入らない)
minify後の依存ツリーをみる方法やツールがあるならお知らせください。
この辺のツールはAlminのファイルサイズをビルド後 gzipで10KB以下にするため、計測する方法を調べてやりました。
- perf(StoreGroup): use lru-map-like insteadof lru-cache by azu · Pull Request #57 · almin/almin
- Reduce file size · Issue #56 · almin/almin
追記(2019-02-06): 現在はwebpack-bundle-analyzer
という優れたビジュアライズツールがあるので、最初はこれを利用することをおすすめします。
もっと詳細なデータをみたい、フィルターしたい場合はwebpackのstats.json
ファイルを見ていくと良さそうです。
- webpack-contrib/webpack-bundle-analyzer: Webpack plugin and CLI utility that represents bundle content as convenient interactive zoomable treemap
- Vendor and code splitting in webpack 2 – Adam Rackis – Medium
おまけ
GitHubリポジトリの指定したファイルのサイズを表示してくれるbadgeサービスもあります。
Badge | URL |
---|---|
Normal size | |
Gzipped size |