Help us understand the problem. What is going on with this article?

不要なPolyfillを削減する

More than 1 year has passed since last update.

Node.js_2 Advent Calendar 2018に空きがあったので、飛び入り参加させてもらうことにしました。

必要だけど微妙なときもある

JavaScriptは、実行環境が多岐にわたる上に、開発者が実行環境を選びづらいという事情もあって、JavaScriptのコードを使って実装の差を補う、PolyfillやPonyfillといったテクニックが存在します。

もちろん、汎用性を求められるライブラリであれば、このような方法で動かせる環境を増やすことは、もちろん有用です。ただ、そうでないプロジェクト作成の場合、「他のライブラリのバージョンが決まっている」あるいは「別なところで対応できる最低限のブラウザが決まってしまう」などの事情によって、Polyfillコードが動く機会がまったく訪れず、単なるバンドルの肥やしにしかならないシチュエーションも存在します。

Webpackで差し替える

自分で呼び出しているものであれば呼ぶコードを書き換えればいいのですが、他のライブラリからの依存関係で参照しているものはそうも行きません。ただ、Webpackにはresolve.aliasという、読み込むモジュールを差し替える機能が存在します。これを使うことで、不要となったPolyfillライブラリをダミーのものに差し替えて、容量を節減することが可能となります。

今回のターゲット

今回対象とするライブラリは、reactjs/react-lifecycles-compatです。React 16.3で加わったgetDerivedStateFromPropsgetSnapshotBeforeUpdateを、それ以前のバージョンのReactでも動かせるようにするためのPolyfillライブラリです。

もちろん、React 16.3以上しか使わないプロジェクトであれば、これは無用の長物と化します。

インターフェースの調査

とはいえ、単に「削除しました」だけではエラーとなりますので、「react-lifecycles-compatのインターフェースは再現して、実際の動作だけ削減する」コードにしないといけません。ソースコードを確認すると、以下のことがわかりました。

  • エクスポートしているのは、polyfillという関数1つ
  • 引数は、クラスコンポーネント1つだけ
  • そのコンポーネントを破壊的に変更して、同じコンポーネントを返す

ということで、インターフェースを守った最低限のコードは、以下のようになります。

const polyfill = Component => Component;

export {polyfill};

aliasで差し替える

的確に当該のモジュールだけを差し替えるために、対象のモジュールはrequire.resolveで指定しましょう。

webpack.config.js(一部)
{
  resolve: {
    alias: {
      [require.resolve('react-lifecycles-compat')]: require.resolve('./relative/path/to/mock')
    }
  }
}

このようにして、不要なPolyfillを追い出すことに成功しました。

jkr_2255
qiitadon
Qiitadon(β)から生まれた Qiita ユーザー・コミュニティです。
https://qiitadon.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away