Node.js_2 Advent Calendar 2018に空きがあったので、飛び入り参加させてもらうことにしました。
必要だけど微妙なときもある
JavaScriptは、実行環境が多岐にわたる上に、開発者が実行環境を選びづらいという事情もあって、JavaScriptのコードを使って実装の差を補う、PolyfillやPonyfillといったテクニックが存在します。
もちろん、汎用性を求められるライブラリであれば、このような方法で動かせる環境を増やすことは、もちろん有用です。ただ、そうでないプロジェクト作成の場合、「他のライブラリのバージョンが決まっている」あるいは「別なところで対応できる最低限のブラウザが決まってしまう」などの事情によって、Polyfillコードが動く機会がまったく訪れず、単なるバンドルの肥やしにしかならないシチュエーションも存在します。
Webpackで差し替える
自分で呼び出しているものであれば呼ぶコードを書き換えればいいのですが、他のライブラリからの依存関係で参照しているものはそうも行きません。ただ、Webpackにはresolve.alias
という、読み込むモジュールを差し替える機能が存在します。これを使うことで、不要となったPolyfillライブラリをダミーのものに差し替えて、容量を節減することが可能となります。
今回のターゲット
今回対象とするライブラリは、reactjs/react-lifecycles-compatです。React 16.3で加わったgetDerivedStateFromProps
やgetSnapshotBeforeUpdate
を、それ以前のバージョンのReactでも動かせるようにするためのPolyfillライブラリです。
もちろん、React 16.3以上しか使わないプロジェクトであれば、これは無用の長物と化します。
インターフェースの調査
とはいえ、単に「削除しました」だけではエラーとなりますので、「react-lifecycles-compat
のインターフェースは再現して、実際の動作だけ削減する」コードにしないといけません。ソースコードを確認すると、以下のことがわかりました。
- エクスポートしているのは、
polyfill
という関数1つ - 引数は、クラスコンポーネント1つだけ
- そのコンポーネントを破壊的に変更して、同じコンポーネントを返す
ということで、インターフェースを守った最低限のコードは、以下のようになります。
const polyfill = Component => Component;
export {polyfill};
alias
で差し替える
的確に当該のモジュールだけを差し替えるために、対象のモジュールはrequire.resolve
で指定しましょう。
{
resolve: {
alias: {
[require.resolve('react-lifecycles-compat')]: require.resolve('./relative/path/to/mock')
}
}
}
このようにして、不要なPolyfillを追い出すことに成功しました。