概要
Webpackのビルド時間を改善する手法としてDllPluginを使ってビルド対象を分割するというものがあります。そのやり方を説明します。
DLLPluginとは
DLLPluginはWebpack公式にも紹介されている方法でビルド対象を分割する事によって劇的にビルドのパフォーマンスを改善してくれます。 https://webpack.js.org/plugins/dll-plugin/
DLLとはダイナミックリンクライブラリの略で、要するに動的にライブラリにリンクしてくれるということなので、事前にライブラリを別のbundleとしてビルドしておいて、それに含まれるライブラリに依存するバンドルは後からライブラリのbundleにリンクするという形を取ります。
これによりライブラリとライブラリを使う側のコードのビルドを分離できるので、都度ライブラリ側のコードをビルドしなくて良くなりビルドが速くなります。
導入
ライブラリ側のファイルのビルドと使う側のファイルを分けるので、webpackの設定は2つ書きます。同時にビルド用のnpmスクリプトも2つ用意します。ライブラリ側をvendorとし、ライブラリを使うアプリケーション側をappとします。
ライブラリ側のビルド
今回はライブラリを詰め合わせたビルドをvendorという名前で作っていきます。
const path = require('path');
const webpack = require('webpack');
const ManifestPlugin = require('webpack-manifest-plugin');
module.exports = {
entry: {
vendor: [
'axios',
],
},
output: {
path: path.resolve(__dirname, 'public/js'),
filename: '[name]-[hash].js',
hashDigestLength: 6,
library: '[name]'
},
plugins: [
new webpack.DllPlugin({
/**
* path
* manifestファイルの出力先
* [name]の部分はentryの名前に変換されるので今回はvendor
*/
path: path.join(__dirname, 'public/js', '[name]-manifest.json'),
/**
* name
* どの空間(global変数)にdll bundleがあるか
* output.libraryに指定した値を使えばよい
*/
name: '[name]'
})
]
};
axiosを分離してビルドする設定を書きました。
これを実行すると
public/js/vendor-[hash].js
public/js/vendor-manifest.json
という2つのファイルが生成されます。
public/js/vendor-[hash].js
はビルド結果が入り、public/js/vendor-manifest.json
の方にはDLLPluginでのリンク用の設定が吐き出されます。
{
"vendor.js": "vendor-ee25a3.js"
}
ライブラリを使うコード側のビルド
app.jsにはaxiosを使うようなコードを予め書いておきます。
const webpack = require('webpack');
module.exports = {
entry: {
app:'./resources/js/app.js',
},
plugins: [
new webpack.DllReferencePlugin({
context: __dirname,
manifest: require('./public/js/vendor-manifest'),
}),
],
... 略 ...
}
これを実行するとapp-[hash].js
が生成されます。
このようにしてDllReferencePluginを使うことでDllPluginで作ったvendor側のファイルを動的に読み込むことができます。
npm script
上2つのビルドはそれぞれ別々に実行できます。最初は依存関係があるのでvendor、appの順にビルドしてください。
{
"private": true,
"scripts": {
"build-app": "webpack --no-progress --hide-modules --mode=production --config=./webpack.js",
"build-vendor": "webpack --no-progress --hide-modules --mode=production --config=./webpack.vendor.js"
},
... 略 ...
}
これによって日々の開発ではapp.js側しかビルドしなくて良いのでビルドが早くなります。
HTML側での読み込み
依存関係に合わせて順番に読むようにして下さい。
<script src="js/vendor-[hash].js"></script>
<script src="js/app-[hash].js"></script>
DllPluginを使ってみて
実際のアプリケーションにDllPluginを導入したところビルド時間が約3分の2ほどに短くなったので、とてもおすすめです。またDllPluginの対象はパスを指定するだけなので外部のライブラリだけでなく開発中のコードもクラス単位でビルドを分離可能なので、枯れていてほとんど変更がない部分についてはどんどんDllPluginの対象にしていくというのが有効だと思います。