主なNode.js独自API
本稿では、Node.jsに存在するがWebブラウザに存在しないAPIを一覧します。こういったAPIの中には一見してNode.jsの独自APIとわかりにくいものもあり、一通りそのようなAPIを把握しておくことでよりポータビリティーの高いコードを書けるようになることが期待できます。
特によく問題になる独自API
- Buffer (Uint8Arrayのラッパーであり、Uint8Array + TextEncoder/TextDecoderでおおよそ代替できる)
- querystring (npmから提供されているqsやquery-stringが代替としてよく使われる)
なぜ独自APIを気にする必要があるのか
モジュールバンドラーの普及により、同一のJavaScriptコードをNode.jsとWebブラウザーの両方で動かすことが容易になりました。
Node.jsのAPIのなかには、Bufferやquerystring, EventEmitterやstreamなどのように外界へのインターフェースではない (= Node.jsとは独立したライブラリとしても提供可能な) ものもいくつか存在します。これらを利用するJavaScriptコードはWebブラウザーでも動くことが期待されるため、WebpackなどのモジュールバンドラーはしばしばこれらのAPIをその互換実装で置き換えてくれますが、残念ながらこういった互換実装はメイン実装ほど積極的に開発されておらず、計画的にまとまった形で開発されているわけでもないようです。 (やや古い資料ですがNode.jsコアモジュールとブラウザ向けShimのギャップについてなどが参考になります)
そのため、以下のような機能で置き換えたほうが信頼性が高くなる可能性があります。
- JavaScriptの標準機能 (
Buffer
→Uint8Array
など) - WebブラウザとNode.jsが直接実装している互いに互換性のある機能 (
crypto
→ SubtleCrypto など) - npm等から入手できる純JavaScript製のライブラリ (
querystring
→qs
,query-string
など)
Node.jsが提供するAPIの種類
グローバル変数として提供されているものは、以下のようにそのまま使うことができます。
Buffer.from("abc")
Node.jsの組み込みモジュールとして提供されているものは、 import
/ require
を通じて利用することができます。
// CommonJS Modules の場合
const fs = require("fs");
const fs = require("node:fs");
// ES Modules の場合
import fs from "fs";
import fs from "node:fs";
process
のように、グローバル変数としても組み込みモジュールとしても提供されているAPIもあります。
global
globalThisの別名です。Webブラウザでは window
と self
がglobalThisの別名として定義されていますが、Node.jsには window
や self
はなく、かわりに global
が定義されています。
Buffer
ArrayBuffer, TypedArray (Uint8Arrayなど), DataView はJavaScriptの標準機能です。一方、BufferはNode.jsの独自機能です。
- ArrayBufferはアロケートされた生のメモリ領域に対するハンドルです。 TypedArray (Uint8Arrayなど) や DataView は ArrayBuffer に対するビューを提供します。
- BufferはNode.jsが独自に定義するUint8Arrayのサブクラスです。
- 元々は独自実装でしたが、2015年頃にNode.js (io.js) v3.0.0でUint8Arrayのサブクラスとして置き換えられました。 (関連: #1825, #2022, 70d1f32 (lib/buffer.js), 8172f45)
現在では、Bufferを使わなければいけない特段の事情はありません。
Node.js APIs accept plain
Uint8Array
s whereverBuffer
s are supported as well.
ただし、Bufferにはstringとの相互変換や入出力に便利な処理がいくつか定義されています。また、Node.js自身のAPIにはBufferを返すものも多く存在しています。もしBufferを使う必要がある場合はBufferとプレーンなUint8Arrayの差分も把握しておくといいかもしれません。
setImmediate / clearImmediate
setImmediateは setTimeout
や queueMicrotask
の仲間で、タイマーを使わずに直接タスクキューにコールバックを登録する関数です。タスクとマイクロタスクについてはJavaScriptの非同期処理をじっくり理解する (1) 実行モデルとタスクキューなどを参照してください。
setImmediateはWebブラウザには存在せず、同等の機能を提供するAPIも存在しません。類似の機能である setTimeout(0)
を使うか、 postMessage
を使ってエミュレートする手段があり、polyfillも存在します。
process
process
はNode.jsプロセスの情報にアクセスするためのAPIであり、ほとんどNode.js固有です。
ただし、モジュールバンドラーにはソースコード中の process.env
に対する参照を一定の規則に基づいて置き換えるルールが実装されていることがあります。特に process.env.NODE_ENV
は慣習的によく使われます。
// process.env.NODE_ENV が定義されている or モジュールバンドラーによって置換されることを期待している
if (process.env.NODE_ENV === "development") {
console.warn("this function is deprecated");
}
組み込みモジュール (1)
組み込みモジュールのうち、一見するとNode.jsのAPIである必要がないものは以下の通りです。
(本稿ではわかりやすさのために node:
をつけていますが、 node:
をつけなくてもimport/require可能であることに注意が必要です)
-
assert
-
node:assert
は不変条件が満たされないときに例外を送出する関数が定義されているライブラリです。 - Jestなどのテストフレームワークはそれぞれがアサーション用の関数を提供しているので、それで置き換えることができます。npm上にも keywords:assert や keywords:assertion でヒットするパッケージが多数存在します。
-
-
node:async_hooks
-
node:async_hooks
は並行動作する複数の非同期処理を区別しながら追跡することを可能にします。詳しくはJavaScriptの非同期処理をじっくり理解する (4) AbortSignal, Event, Async Context#AsyncHooks, AsyncLocalStorageを参照してください。 - async_hooksは非同期I/OサーバーであるNode.jsに特有の需要であり、V8に手を入れることで実現されています。Webブラウザを含めた広汎なJavaScript処理系で同じ機能を実現する見込みはありません。
-
-
node:console
-
node:console
はConsole
クラスを提供します。シングルトンであるconsole
と同等の機能をもつロガーを自由に生成することができます。 - シングルトンの
console
はNode.jsとWebブラウザで共通で利用できますが、Console
はNode.jsにしかありません。
-
-
node:crypto
-
node:crypto
は暗号関連処理を提供します。 (暗号学的な安全性が求められる処理を自分で実装するのはやめましょう) - グローバル変数
crypto
,Crypto
,CryptoKey
,SubtleCrypto
はWeb Cryptography APIと互換性があるため、こちらを使うのがよいでしょう。- ただし、現在は
--experimental-global-webcrypto
が必要です。require("node:crypto").webcrypto
でも同APIにアクセスできます。
- ただし、現在は
-
-
node:events
- Node.jsのイベント通知機構 EventEmitter を提供します。
- ブラウザ互換の Event / EventTarget とおおよそ同等のため、 EventTarget を使うほうがよいでしょう。
-
node:punycode
-
node:punycode
はPunycodeのエンコード・デコード処理を実装しています。 - 非推奨APIです。keywords:punycodeなどで代替実装を探すとよいでしょう。
-
-
node:querystring
-
node:querystring
はクエリ文字列のパーサーです。 - 非推奨ではないもののレガシーコード向けAPIとしてマークされています。
- Webブラウザ互換のURLライブラリのURLSearchParamsでの置き換えが推奨されています。
- qsやquery-stringなども広く使われています。
-
-
node:stream
-
node:stream
はストリーム (一括ではなく先頭から少しずつ送受信されるデータ) を扱うためのライブラリです。 -
WHATWG Streamsの実装が
node:stream/web
から提供されているため、可能であればこちらを使うのがよいでしょう。 - 現時点では
node:stream/web
の内容はグローバル変数としては提供されていません。将来的にグローバル変数として提供されるようになったら、そちらに移行するのがよいでしょう。
-
-
node:string_decoder
-
node:string_decoder
は名前の通り、UTF-8等でエンコードされたデータをstring
にデコードするライブラリです。 - 現在はWebブラウザ互換の
TextDecoder
があるので、そちらを使うのがよいでしょう。
-
-
node:timers
-
node:timers
はsetTimeout
などのタイマー関連APIを提供します。 -
active
,enroll
,unenroll
など非推奨化されたAPIを除き、グローバル変数として提供されます。- このうち
setTimeout
,clearTimeout
,setInterval
,clearInterval
はWebブラウザのものとほぼ同等の使い方ができます。 (独自APIを備えたオブジェクトが返ってくるという違いがある程度) -
setImmediate
,clearImmediate
には同等のAPIはありません (前述の記述を参照)
- このうち
-
-
node:url
-
node:url
はURL操作 (パーサー等) を提供します。 - Webブラウザ互換の
URL
がグローバル変数として提供されているので、そちらを使うのがよいでしょう。
-
-
node:util
-
node:util
はごった煮です。 - ひとつひとつの代替を紹介するのは大変なので省略します。
-
-
node:zlib
-
node:zlib
は名前の通りzlibのバインディングを提供します。 - ポータビリティーが必要であればCライブラリに依存するわけにはいかないので、npmで純JSの実装を探すといいかもしれません。
-
組み込みモジュール (2)
よりNode.js固有に近いものには以下のようなものがあります。こういったAPIを使っている場合は本質的にNode.jsに固有の処理を書いている可能性が高いので、それぞれの詳しい説明は省略します。
-
node:process
-
process
グローバル変数と同じ。
-
-
node:diagnostics_channel
- ライブラリから警告等の診断情報を流すための汎用API。
-
node:wasi
-
WebAssembly
で起動するWebAssemblyプログラムに外部環境へのアクセス手段を提供するモジュール。
-
-
node:path
- ファイルパスの操作用ですが、ファイルパスの振舞いはOS依存なので実質的にはスタンドアロン環境に固有の処理と考えられます。
- プロセス・スレッド関連
node:child_process
node:cluster
node:worker_threads
- 各種I/Oモジュール
node:dns
node:fs
node:http
node:http2
-
node:https
-
http
,http2
,https
を使った処理はfetch
で置き換えられる可能性があります。 -
fetch
はNode.jsによる公式実装が実験的に利用可能なほか、非公式のnode-fetchが長年デファクトスタンダードとして使われています。-
cross-fetch
やisomorphic-fetch
など、fetch
のpolyfillを環境に応じて出し分けるライブラリもあります。
-
-
node:net
node:os
node:readline
node:tls
node:tty
node:dgram
- Node.js固有の機能へのアクセス
node:domain
node:inspector
node:module
-
node:perf_hooks
-
require("node:perf_hooks").performance
はglobalThis.performance
と同じもので、これはWebブラウザとある程度の互換性があります。
-
node:repl
node:trace_events
node:v8
node:vm
CommonJS Modules 向けAPI
require
, module
, exports
, __dirname
, __filename
はCommonJS Modules向けAPIです。モジュールスコープで自動的に定義される名前であり、厳密にはグローバル変数ではありません。
WebpackなどCommonJS Modulesをサポートしたモジュールバンドラーを使う場合、これらのAPIは特別な指定がなくても利用可能です。
Webブラウザと共通のAPI
ここに挙げられているAPIがNode.jsとWebブラウザで完全に互換な振舞いをするとは限らないことに注意してください。
- ECMAScript (ECMA-262) のグローバル変数
-
globalThis
,undefined
eval
-
Object
,Function
,Array
,Number
,Boolean
,String
,Symbol
,BigInt
-
Proxy
,Reflect
,FinalizationRegistry
,WeakRef
-
Error
,AggregateError
,EvalError
,RangeError
,ReferenceError
,SyntaxError
,TypeError
,URIError
-
parseFloat
,parseInt
,isFinite
,isNaN
,Infinity
,NaN
-
decodeURI
,decodeURIComponent
,encodeURI
,encodeURIComponent
,escape
,unescape
-
Set
,Map
,WeakSet
,WeakMap
-
ArrayBuffer
,Uint8Array
,Uint8ClampedArray
,Int8Array
,Uint16Array
,Int16Array
,Uint32Array
,Int32Array
,BigUint64Array
,BitInt64Array
,Float32Array
,Float64Array
,DataView
-
SharedArrayBuffer
,Atomics
-
Date
,Proimse
,RegExp
-
JSON
,Math
-
-
ECMAScript Internationalization API (ECMA-402) のグローバル変数
Intl
URL
,URLSearchParams
TextDecoder
,TextEncoder
atob
,btoa
setTimeout
,clearTimeout
,setInterval
,clearInterval
,queueMicrotask
-
crypto
,Crypto
,CryptoKey
,SubtleCrypto
-
--experimental-global-webcrypto
フラグが必要。
-
performance
structuredClone
console
Event
,EventTarget
DOMException
AbortController
,AbortSignal
MessagePort
,MessageChannel
,MessageEvent
-
fetch
,Request
,Response
,Headers
,FormData
-
--experimental-fetch
フラグが必要。
-
WebAssembly
Discussion
ちょっとした補足です。
setImmediate
は元々 Microsoft が提案した仕様で、IE10 以降のブラウザで使うことができました。旧 Edge にも搭載されていましたが、Chromium Edge になった段階で廃止されたと言う認識です。ちなみに core-js にて polyfill が提供されています。