Posted at

webpackを可視化するツールを紹介

More than 1 year has passed since last update.

フロントエンドのビルド(webpack)に関わる部分でパフォーマンス改善を考える時に、

現状を可視化するため、いくつかプラグインを使ってみましたので、軽く紹介したいと思います

可視化したい対象は以下の2つです

・webpackの速度改善の為、遅いloaderやpluginを知りたい

・バンドルファイルのサイズを減らしたいので、バンドルファイル内の各パッケージがどのくらいの容量を占めているか知りたい

今回分析に使ったコードはこちらです

https://github.com/kurosame/vuejs-boilerplate


遅いloaderやpluginを知りたい


speed-measure-webpack-plugin

$ yarn add --dev speed-measure-webpack-plugin


webpack.config.js

const SpeedMeasurePlugin = require('speed-measure-webpack-plugin')

const smp = new SpeedMeasurePlugin()

// webpackConfigをラップする
module.exports = smp.wrap({
entry: {
...
})


$ npx webpack

■ 結果

 2018-04-17 18.54.38.png

全体で約6.5秒くらいかかってるのですが、そのうちのほとんどがTypeScript関連の処理に時間がかかっているのが分かります

(babel-loader and ts-loader and tslint-loaderの所)

実際のwebpack設定を見ると以下のようになってました


webpack.config.js

...

module.exports = {
module: {
rules: [
...
{
test: /\.ts$/,
use: [
{
loader: 'babel-loader?cacheDirectory'
},
{
loader: 'ts-loader',
options: {
appendTsSuffixTo: [/\.vue$/],
transpileOnly: true
}
},
{
loader: 'tslint-loader',
options: {
typeCheck: true
}
}
],
exclude: /node_modules/
}
...
]
}
}

ここをターゲットに調べるとtslint-loaderのtypeCheckに3.5秒かかっていることが分かりました

少し調べるとtslint-loaderのtypeCheckが遅いことがissuesに上がってました

https://github.com/wbuchwalter/tslint-loader/issues/76


バンドルファイル内の各パッケージがどのくらいの容量を占めているか知りたい


webpack-bundle-analyzer

$ yarn add --dev webpack-bundle-analyzer


webpack.config.js

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin

module.exports = {
...
plugins: [
new BundleAnalyzerPlugin()
]
}


$ npx webpack

ブラウザがhttp://127.0.0.1:8888/で立ち上がり、以下のような結果が表示されます

 2018-04-17 17.52.47.png

今回分析に使ったコードでは、webpack実行時に2つのファイルを出力するようにしています

実装したコードをバンドルしたbuild-[ハッシュ値].jsとサードパーティー系のパッケージのみをバンドルしたvendor-[ハッシュ値].jsになります

vendorの方がサイズが大きくなると予想してましたが、結果はほぼ同じくらいのサイズでした

結果を見てみると、babel-runtimeとnormalize.cssらへんが大きいことが分かります

babel-runtimeは新しい書き方(EcmaScript)で実装したコードをレガシーブラウザでも動くように変換するライブラリなので、

IEなどをターゲットにしているプロジェクトだと使わないわけにはいきません

normalize.cssはクロスブラウザでデフォルトのスタイルの差異を無くすため、初期デフォルトスタイルを提供してくれるライブラリです

今まで意識してなかったので、ここまで重いとは思いませんでした。。

調べてみると、今回分析に使ったコードではnormalize.cssはv7.0.0を使っています。

現在の最新はv8.0.0でこのバージョンでは古いバージョンのブラウザを対象外としている為、大幅な軽量化がされたみたいです

単純にバージョンを上げるだけでもバンドルサイズの削減ができそうです

また、IEをサポートする必要がない場合は、modern-normalizeというライブラリを検討するのも良さそうというもの分かりました

https://github.com/sindresorhus/modern-normalize

またnormalize.cssを使わずに自作する選択肢もありかもしれません


webpack-bundle-size-analyzer

webpack-bundle-analyzerだとvendorが上手く可視化できなかったので、webpack-bundle-size-analyzerを使って可視化しました

$ npx webpack --config webpack.vendor.config.js --profile --json > stats.json

$ npx webpack-bundle-size-analyzer stats.json

 2018-04-18 14.14.41.png


source-map-explorer

こちらもwebpack-bundle-analyzerと同様にバンドルファイルの中身を可視化できます


webpack.config.js

module.exports = {

output: {
filename: '[name]-[hash].js',
path: path.resolve(__dirname, 'dist'),
sourceMapFilename: '[file].map',
},
devtool: '#source-map' // inline-source-mapだと駄目だった
}

$ npx source-map-explorer dist/bundle-[ハッシュ値].js

 2018-04-18 11.47.26.png

こちらは全体のサイズやパーセントが見れるし、グリッドデザインで見やすいです


webpack-visualizer-plugin

こちらもwebpack-bundle-analyzerと同様にバンドルファイルの中身を可視化できます

$ yarn add --dev webpack-visualizer-plugin


webpack.config.js

const Visualizer = require('webpack-visualizer-plugin')

module.exports = {
...
plugins: [
new Visualizer()
]
}


先程のプラグインと比べて、だいぶ見せ方が違いますね

 2018-04-18 14.28.17.png

カーソルを合わすと、以下のようにサイズとパーセントが表示されます

 2018-04-18 14.29.10.png