フロントエンドのビルド(webpack)に関わる部分でパフォーマンス改善を考える時に、
現状を可視化するため、いくつかプラグインを使ってみましたので、軽く紹介したいと思います
可視化したい対象は以下の2つです
・webpackの速度改善の為、遅いloaderやpluginを知りたい
・バンドルファイルのサイズを減らしたいので、バンドルファイル内の各パッケージがどのくらいの容量を占めているか知りたい
今回分析に使ったコードはこちらです
https://github.com/kurosame/vuejs-boilerplate
遅いloaderやpluginを知りたい
speed-measure-webpack-plugin
$ yarn add --dev speed-measure-webpack-plugin
const SpeedMeasurePlugin = require('speed-measure-webpack-plugin')
const smp = new SpeedMeasurePlugin()
// webpackConfigをラップする
module.exports = smp.wrap({
entry: {
...
})
$ npx webpack
全体で約6.5秒くらいかかってるのですが、そのうちのほとんどがTypeScript関連の処理に時間がかかっているのが分かります
(babel-loader and ts-loader and tslint-loaderの所)
実際のwebpack設定を見ると以下のようになってました
...
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
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
module.exports = {
...
plugins: [
new BundleAnalyzerPlugin()
]
}
$ npx webpack
ブラウザがhttp://127.0.0.1:8888/
で立ち上がり、以下のような結果が表示されます
今回分析に使ったコードでは、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
source-map-explorer
こちらもwebpack-bundle-analyzerと同様にバンドルファイルの中身を可視化できます
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
こちらは全体のサイズやパーセントが見れるし、グリッドデザインで見やすいです
webpack-visualizer-plugin
こちらもwebpack-bundle-analyzerと同様にバンドルファイルの中身を可視化できます
$ yarn add --dev webpack-visualizer-plugin
const Visualizer = require('webpack-visualizer-plugin')
module.exports = {
...
plugins: [
new Visualizer()
]
}
先程のプラグインと比べて、だいぶ見せ方が違いますね
カーソルを合わすと、以下のようにサイズとパーセントが表示されます