Webpackのビルドにあるときからsetimmediate
などのパッケージが含まれて容量を食うようになってしまったのですが、これは設定で回避できることが判明しました。
setImmediate
とは
JavaScript環境ではおなじみのsetTimeout
ですが、処理を非同期にするだけの目的でも使われます。ただ、待ち時間を完全に0とすることはできず、4ミリ秒程度待たされることとなります。
そこで、「非同期にしたいけど、できるだけ待たせたくない」という需要が生じるわけですが、環境によってはそれがsetImmediate
という名前で実装されています。そして、存在しないブラウザ環境でもpostMessage
を使うことで実装可能です。
Webpack時の問題
setImmediate
のある環境は、Node.js・IE・Edgeとなっていて、ChromeやFirefoxには存在しません。そして、Node.jsに存在することもあって、WebpackではコードにグローバルなsetImmediate
が登場すると、YuzuJS/setImmediateを使ったPolyfillへと置き換えていきます。
さらに、YuzuJS/setImmediateのコード内で、古いNode向けのコードとしてprocess.nextTick
が使われているために、これもPolyfillされます。結果、defunctzombie/node-processとbrowserify/timers-browserifyも入って、3つで都合4.2kB、Gzip後でも1.6kBという容量を消費してしまいます。
不要な場面
もちろん、Node前提のライブラリで、setImmediate
に問答無用で依存しているライブラリであれば、頑張ってPolyfillをかける必要もあるかもしれません1。
一方で、ブラウザ向けのライブラリの場合、setImmediate
がネイティブのある環境が限られますので、以下のような「setImmediate
があれば使う」コードを見かけます。
const asyncRun = typeof setImmediate === 'function' ?
func => setImmediate(func) :
func => setTimeout(func, 0);
標準設定のWebpackでは、このようなコードにもPolyfillを施していってしまいます。
設定で止められる
ちょうど@fortawesome/fontawesome-svg-core
で、「Promise
がない環境のPolyfillコード2」でsetImmediate
があれば使うようになっていて、かなり過剰感もあったので削減したくなりました。調べてみると、webpack.config.js
でnode.setImmediate = false
とすることで、setImmediate
のPolyfillが省略できることが判明しました。
指定することで、3つのパッケージはきれいに消滅しました。