目的
require
の引数に変数がある場合に、
webpackはその変数を「全ての文字列」として解釈し、
マッチする全てのファイルをバンドル対象としますが、
その処理を上書きして、一部のファイルのみバンドル対象とするために使います。
使い方
Usageには以下のように定義されています。
2〜4番目の引数(?
があるもの)は任意項目のようですが、
JavaScriptにこのような記法があるわけではなく、
自前で引数の型をチェックして、
どの項目が指定されたかどうかを判定しています1。
new webpack.ContextReplacementPlugin(
resourceRegExp: RegExp,
newContentResource?: string,
newContentRecursive?: boolean,
newContentRegExp?: RegExp
)
一番簡単な例として、Moment.jsのロケール設定を置き換えるものが挙げられています。
new webpack.ContextReplacementPlugin(
/moment[\/\\]locale$/,
/de|fr|hu/
)
1番目の引数はresourceRegExp
、2番目の引数はnewContentRegExp
なのですが、
これをどう指定すればいいのか、
それはMoment.jsのソースコードを読む必要があります。
Moment.js 2.20.1の1844行目あたりに以下のコードがあります。
var aliasedRequire = require;
aliasedRequire('./locale/' + name);
1行目はrequireのaliasを作っているだけなので、問題は2行目です。
どうやらこれをwebpackが解釈する時に、
name
変数を任意の文字列にマッチさせています。
ここでは./locale/.*
になっていますが、
実際はMoment.jsの内部でのrequireなので、
実ファイルでは、node_modules/moment/locale/.*
にマッチします。
このとき、置き換え前のディレクトリはmoment/locale
,
マッチする正規表現は.*
になっています。
これをそれぞれ、/moment[\/\\]locale$/
,
/de|fr|hu/
という正規表現に置き換えるのがこのプラグインの目的です。
なお、この/moment/locale$/
でなく /moment[\/\\]locale$/
になっている
理由は、Windows対応のためのようです。
また、newContentRegexp
に拡張子がついていないのは、
moduleには拡張子は不要(自動補完される)ためです。