LoginSignup
6
3

More than 5 years have passed since last update.

WebpackバンドルにsetImmediateがいらないときに

Posted at

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-processbrowserify/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.jsnode.setImmediate = falseとすることで、setImmediateのPolyfillが省略できることが判明しました。

Node - Webpack configuration

指定することで、3つのパッケージはきれいに消滅しました。


  1. もっとも、process.nextTick向けのPolyfillはほとんどの用法で余計だと思われます。 

  2. 別な場所でもPromiseが必要なのでグローバルにPolyfillしてあり、これ自体が不要なのですが、そこはいったん置いておきます。 

6
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3