プラグイン
プラグインとは
ローダーはバンドル前に作用するが、プラグインはバンドルファイルに作用する。
ProvidePlugin
任意のモジュールを全てのファイル(モジュール)の変数として利用可能にするプラグイン。
ファイルごとにimport文で読み込む必要がなくなる。
※npmパッケージのインストールは不要。webpackに組み込まれている。
- webpack.config.jsにwebpackのrequire文とpluginsプロパティを追加
const webpack = require('webpack');
// 〜省略〜
plugins: [
// ProvidePlugin を利用する
new webpack.ProvidePlugin({
// 外部モジュールであるjqueryを、全てのファイル上で変数$として利用できるようになる
$: 'jquery'
})
]
※ これでimport $ from ‘jquery’;を書かなくても、全てのjsファイルで変数$が使えるようになる。
webpack-bundle-analyzer
バンドルされたモジュールのファイルサイズを確認できるプラグイン。
npm install --save-dev webpack-bundle-analyzer
- webpack.config.jsにwebpack-bundle-analyzerのrequire文とpluginsプロパティを追加
const { BundleAnalyzerPlugin } = require('webpack-bundle-analyzer');
// 〜省略〜
plugins: [
new BundleAnalyzerPlugin()
]
実行すると、一番上にバンドルしたファイル、その下にその中身が階層で表示される。
clean-webpack-plugin
バンドル時に、ouput.pathで指定したディレクトリ内のファイルを削除するプラグイン。
npm install --save-dev clean-webpack-plugin
- webpack.config.jsにclean-webpack-pluginのrequire文とpluginsプロパティを追加
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
// 〜省略〜
plugins: [
new CleanWebpackPlugin()
]
便利な機能
エントリーポイントを複数指定する
entryが1つの場合は文字列で指定するが、複数の場合はオブジェクトで指定する。
バンドルファイル名には、filename: '[name].js',
のようにenrtyのキー名を使うことができる。 (以下の例の場合、app.bundle.js と search.bundle.js が出力される)
// 1つの場合は文字列で指定する
// entry: './src/js/app.js',
// 複数の場合はオブジェクトで指定する
entry: {
app: './src/js/app.js',
search: './src/js/search.js'
},
// 出力の設定
output: {
// 出力するファイル名
filename: '[name].js',
// 〜省略〜
},
watchモード
webpack.config.jsにwatch: ture
を追加する、またはwebpackコマンドに–watchオプションを付与するとwatchモードとなり、ファイルが更新される度に自動的にバンドルが行われる。
npm srciptで"dev": "webpack --watch --mode=development",
"build": "webpack --mode=production"
としてmodeとwatchモードを分けると便利。
webpack-dev-server
npm install --save-dev webpack-dev-server
- webpack.config.jsのoutputプロパティにpublicPathを追加、devServerプロパティを追加
webpack-dev-server
で実行
(またはpackage.jsonのscriptに”start”: “webpack-dev-server”を追加してnpm run start
とする)
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'public/js'),
publicPath: '/js/' // ブラウザからバンドルにアクセスする際のパス
},
// 〜省略〜
devServer: {
open: true, // サーバー起動時にブラウザを自動的に起動する
port: 9000,
contentBase: './public' // コンテンツのルートディレクトリ
}
ソースマップ
ソースマップとはバンドルしたファイルと元のファイルを関連付けるファイルであり、バンドル前のコードを確認できるためデバッグがしやすくなる。
開発者ツールでは、sourcesタブのwebpack://の配下に圧縮前のファイルが表示される。
modeがdevelopmentの場合は、devtool: 'eval'
としてソースマップが生成される。 ‘eval’はローダーで変換された後のコードなので、変換前のソースマップが必要な場合は’source-map’を指定する。
- webpack.config.jsにdevtoolプロパティを追
devtool: 'source-map'
設定ファイルを分ける
本番用と開発用で設定ファイルを分ける場合は、実行時に–configオプションを指定する。
npm srciptで"dev": "webpack --watch --mode=development --config webpack.dev.config.js",
"build": "webpack --mode=production --config webpack.prod.config.js"
として分けると便利。
共通部分をwebpack.base.config.jsのようなファイルに記述し、差分だけ別ファイルにしたい場合はwebpack-mergeを使う。
npm install --save-dev webpack-merge
- 本番用、開発用設定ファイルに共通設定読み込み用の記述を追加
const merge = require('webpack-merge');
const baseConfig = require('./webpack.base.config.js');
// 共通設定(baseConfig)をマージする
module.exports = merge(baseConfig, {
mode: 'development',
devtool: 'source-map'
});
terser-webpack-plugin
productionモードで有効になるoptimization.minimizerを上書きするためのプラグイン。
productionではconsole.logやコメントを出力させたくない場合などに使う。
npm install --save-dev terser-webpack-plugin
- webpack.base.config.jsにoptimization.minimizerの設定を追加
const TerserPlugin = require('terser-webpack-plugin');
// 〜省略〜
optimization: {
minimizer: [
new TerserPlugin({
terserOptions: {
compress: { drop_console: true }, // consoleを除去
output: { comments: false }, // コメントを除去
}
})
]
}
最適化
Tree Shaking
Tree Shakingとは、デッドコード(使われていない不要なコード)を除去する機能のことである。webpack4では、productionモードでビルドすると自動的にTree Shakingを使ってビルドされる。import { upperCase } from 'lodash-es';
のようにES2015のimport/export構文(ES Modules)を使うと、Tree Shakingが行われる。 import _ from 'lodash-es';
のようにモジュール全てをインポートするとTree Shakingは行われない。
※lodashはCommonJSなのでlodash-esを使う必要がある。
SplitChunksPlugin
複数のエントリーポイントで同じモジュールを利用している場合、デフォルトだとそれぞれのバンドルファイルにモジュールもバンドルされてしまう。 SplitChunksPluginを利用すると、共通で利用しているモジュールだけのバンドルファイルを別に生成してくれる。
例えば、エントリーポイントapp.jsとapp2.jsが共にjQueryとlodashを使っている場合、2つのバンドルファイルとは別にvendor.bunle.jsのようなファイルを生成してくれる。
※ SplitChunksPluginはnpmパッケージのインストールは不要。webpackに組み込まれている。
- webpack.config.jsにoptimization.splitChunksの設定を追加
optimization: {
splitChunks: {
cacheGroups: {
// 今回のプロパティ名は vendor だが、ここは任意のもので良い
vendor: {
test: /node_modules/, // node_modules配下のモジュールをバンドル対象とする
name: 'vendor', // 出力するファイル名 今回は 'vendor' で、output.filename が '[name].bundle.js' のため、vendor.bundle.js が出力される。
chunks: 'initial', // 共通モジュールとしてバンドルする対象の設定
// webpack はデフォルトでいくつかの splitChunks の設定が有効になる。enforceをtrueにすれば、それらの設定の
// splitChunks.minSize, splitChunks.minChunks, splitChunks.maxAsyncRequests, splitChunks.maxInitialRequests を無効にできる
enforce: true
}
}
}