追記(2018-12-25): 次のレポートに同様 + 追加した内容を公開しています。
この文章は、現在進行形で機能追加や仕様変更が行われているNode.jsコアモジュールとブラウザ向けShimにおける挙動の違い(ギャップ)が広がってきている問題について調べたものです。
ここでは https://nodejs.org/api/ に掲載されているうち assert
のようにNode.jsにバンドルされているモジュールのことをNode.jsコアモジュールと呼びます。コアモジュールはNode.jsでの利用のみを想定しているため、Node.jsに依存した処理を多く含んでいます。そのため、コアモジュールのコードをコピーしてブラウザなどで動かすことは難しいです。
webpackやbrowserifyなどのbundlerは、コード中にあるコアモジュールを代替モジュールへとすり替えます。この代替モジュールはブラウザ向けShimライブラリとよび、このShimライブラリはブラウザで動くようにNode.jsコアモジュールと同等またはStub的な実装をしています。
Note:
ここでPolyfillではなくShimと呼んでいるのは、全く同じ挙動を目的にした実装ではないため。
そもそもブラウザには存在しない機能を扱うprocess
やsys
などがあり、これらはダミーの値を返す実装になっている。
webpackとbrowserifyは変換時に、コード中に現れるassert
モジュールをcommonjs-assertというShimライブラリにすり替えます。
webpackとbrowserifyが利用するshimライブラリは次の場所で管理されています。
- webpack:
- browserify:
この文章の本題であるNode.jsコアモジュールとブラウザ向けShimのギャップがあったものをまとめた表です。 ここでいうギャップというのは、次のようなケースを並べています。
- Node.jsコアモジュールで追加されたAPIがShimライブラリには存在しない
- Node.jsコアモジュールとShimライブラリで挙動が異なる
- 利用されているShimライブラリがDeprecatedになっている
これらの調査結果については次のリポジトリで管理しています。最新の状況もこのリポジトリに反映しています。 そのため次の表は古くなっている可能性があります。
この文章は、webpackやbrowserifyを使っているとあまり意識されないshimライブラリに潜在的な問題があることを調べる目的で書きました。この問題の難しさは各shimライブラリの管理者やバランスが異なるにもかかわらず、shimライブラリ群として暗黙的に参照されている点です。そのため、この問題の根本がどこにあるのかがはっきりせず、どこにIssueを立てるかが難しいです。またIssueを立てた場合もそれを解決するのはかなりの根気が必要になる気がします。 この問題の解決にそこまでのモチベーションを持つことが難しかったので、調査だけにとどめました。
多くのコアモジュールにおいては、問題が表面化しない可能性もあります。しかし、assert
、events
、url
はブラウザ向けとしてよく使われているにもかかわらず差異が分かる程度にはあります。
また、これらの問題が解決できた場合にもwebpackやbrowserifyにはShimライブラリのバージョンを扱う仕組みがないため、互換性の問題が発生するかもしれません。
- Node.js Errors — Changes you need to know about – Node.js Collection – Medium
assert
結果のError#name
などが異なるため、Node.jsでは通るがブラウザ(Shim)では失敗するテストができる- MapやSetなどES2015以降のビルトインオブジェクトに対応していない
- Node v7 で入った WHATWG URL 実装について | blog.jxck.io
- Node.jsがブラウザのWHATWG URLをサポートしたが、ブラウザ(Shim)ではサポートされていない
この問題はハンドリングしている人が誰もいない気がしているので、表面化するまで問題にならない可能性があります。 ただの杞憂に終わっていつのまにか解決している可能性もありますが、どこかが主導となって解決していくのが適切だと思っています。その適切なパスがどこにあるのがわからなかったので、分かる人は手伝ってください。
このコアモジュールのAPIも挙動が異なるという点を知っている人は次のリポジトリにPRをください。