Instantly share code, notes, and snippets.

Embed
What would you like to do?
Node.jsコアモジュールとブラウザ向けShimの挙動の違い(ギャップ)について

Node.jsコアモジュールとブラウザ向けShimのギャップについて

この文章は、現在進行形で機能追加や仕様変更が行われているNode.jsコアモジュールとブラウザ向けShimにおける挙動の違い(ギャップ)が広がってきている問題について調べたものです。

ここでは https://nodejs.org/api/ に掲載されているうち assertのようにNode.jsにバンドルされているモジュールのことをNode.jsコアモジュールと呼びます。コアモジュールはNode.jsでの利用のみを想定しているため、Node.jsに依存した処理を多く含んでいます。そのため、コアモジュールのコードをコピーしてブラウザなどで動かすことは難しいです。

webpackbrowserifyなどのbundlerは、コード中にあるコアモジュールを代替モジュールへとすり替えます。この代替モジュールはブラウザ向けShimライブラリとよび、このShimライブラリはブラウザで動くようにNode.jsコアモジュールと同等またはStub的な実装をしています。

Note:

ここでPolyfillではなくShimと呼んでいるのは、全く同じ挙動を目的にした実装ではないため。 そもそもブラウザには存在しない機能を扱うprocesssysなどがあり、これらはダミーの値を返す実装になっている。

Node.jsコアモジュールのShimライブラリの例

webpackとbrowserifyは変換時に、コード中に現れるassertモジュールをcommonjs-assertというShimライブラリにすり替えます。

Shim library

webpackとbrowserifyが利用するshimライブラリは次の場所で管理されています。

機能のギャップ

この文章の本題であるNode.jsコアモジュールとブラウザ向けShimのギャップがあったものをまとめた表です。 ここでいうギャップというのは、次のようなケースを並べています。

  • Node.jsコアモジュールで追加されたAPIがShimライブラリには存在しない
  • Node.jsコアモジュールとShimライブラリで挙動が異なる
  • 利用されているShimライブラリがDeprecatedになっている

これらの調査結果については次のリポジトリで管理しています。最新の状況もこのリポジトリに反映しています。 そのため次の表は古くなっている可能性があります。

Node.js Browser shim Issue Link
assert defunctzombie/commonjs-assert Error code and Error message Issue, Article
assert.deepEqual support Map, Set, Iterator etc... Issue, Document, Release
buffer feross/buffer ---
child_process --- ---
cluster --- ---
console Raynos/console-browserify ---
constants juliangruber/constants-browserify ---
crypto crypto-browserify/crypto-browserify ---
dgram --- ---
dns --- ---
domain bevry/domain-browser ---
events Gozala/events eventNames Issue
getMaxListeners Issue
prependListener Issue
prependOnceListener Issue
fs --- ---
http jhiesey/stream-http ---
https substack/https-browserify ---
module --- ---
net --- ---
os CoderPuppy/os-browserify os.constants
path substack/path-browserify path.posix Issue
path.parse(path) Issue
path.win32
path.format(pathObject)
process shtylman/node-process process.channel
process.platform Issue
process.execArgv Issue
process.cpuUsage([previousValue])
process.emitWarning(warning[, options])
punycode bestiejs/punycode.js ---
querystring mike-spainhower/querystring ---
readline --- ---
repl --- ---
stream substack/stream-browserify ---
string_decoder rvagg/string_decoder Module is deprecated Repository
sys defunctzombie/node-util TODO
timers jryans/timers-browserify ---
tls --- ---
tty substack/tty-browserify ---
url defunctzombie/node-url WHATWG URL API support Release, Document, Issue
url.format support WHATWG URL Release, Document
util defunctzombie/node-util util.callbackify(original)
util.inspect.custom
util.inspect.defaultOptions
util.promisify(original)
util.promisify.custom
util.inspect() options maxArrayLength, breakLength
vm substack/vm-browserify TODO
zlib devongovett/browserify-zlib zlib.bytesRead

おわりに

この文章は、webpackやbrowserifyを使っているとあまり意識されないshimライブラリに潜在的な問題があることを調べる目的で書きました。この問題の難しさは各shimライブラリの管理者やバランスが異なるにもかかわらず、shimライブラリ群として暗黙的に参照されている点です。そのため、この問題の根本がどこにあるのかがはっきりせず、どこにIssueを立てるかが難しいです。またIssueを立てた場合もそれを解決するのはかなりの根気が必要になる気がします。 この問題の解決にそこまでのモチベーションを持つことが難しかったので、調査だけにとどめました。

多くのコアモジュールにおいては、問題が表面化しない可能性もあります。しかし、asserteventsurlはブラウザ向けとしてよく使われているにもかかわらず差異が分かる程度にはあります。 また、これらの問題が解決できた場合にもwebpackやbrowserifyにはShimライブラリのバージョンを扱う仕組みがないため、互換性の問題が発生するかもしれません。

この問題はハンドリングしている人が誰もいない気がしているので、表面化するまで問題にならない可能性があります。 ただの杞憂に終わっていつのまにか解決している可能性もありますが、どこかが主導となって解決していくのが適切だと思っています。その適切なパスがどこにあるのがわからなかったので、分かる人は手伝ってください。

このコアモジュールのAPIも挙動が異なるという点を知っている人は次のリポジトリにPRをください。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment