別にしんどくないブログ

技術のことや読書メモを書いています

Node.js v25の主な変更点

nodejs logo
引用元: https://nodejs.org/en/about/branding

2025 年 10 月 16 日(日本時間)にリリースされた Node.js v25 の主な変更点を紹介します。

nodejs.org

記事内のサンプルコードはすべて以下のリポジトリにあります。

github.com

V8 のアップデートによる高速化

github.com

JavaScript エンジンの V8 が v13.6 から v14.1 にアップデートしました。

以下の変更により実行速度が向上しました。

  • JSON.stringifyの高速化
  • WebAssembly と JIT パイプラインの最適化

以下の記事によると、JSON.stringifyのパフォーマンスを 2 倍以上に向上させたと書かれています。 v8.dev

オブジェクトのシリアライズによって副作用が発生しないことを V8 が認識できる場合、JSON.stringifyのパフォーマンスが大幅に向上します。 ただし、以下のような場合は副作用が発生する可能性があるため、パフォーマンスの向上は見込めません。

  • オブジェクトに toJSONメソッドが定義されている場合
  • replacer引数が指定されている場合
  • space引数が指定されている場合

これらについては MDN のドキュメントに詳しく書かれています。 developer.mozilla.org

以下のサンプルコードは MDN のドキュメントから引用したreplacer引数を使った例です。

function replacer(key, value) {
  // プロパティをフィルターする
  if (typeof value === "string") {
    return undefined;
  }
  return value;
}

const foo = {
  foundation: "Mozilla",
  model: "box",
  week: 45,
  transport: "car",
  month: 7,
};
JSON.stringify(foo, replacer);
// '{"week":45,"month":7}'

以下はspace引数を使った例です。よく使うのではないでしょうか。

const obj = { a: 1, b: 2, c: 3 };
JSON.stringify(obj, null, 2);
/*
`{
  "a": 1,
  "b": 2,
  "c": 3
}`
*/

以下はtoJSONメソッドを定義した例です。

const obj = {
  a: 1,
  b: 2,
  toJSON() {
    return { a: this.b, b: this.a };
  },
};
JSON.stringify(obj);
// '{"a":2,"b":1}'

これらを利用しないように気をつけていれば、JSON.stringifyのパフォーマンスが向上します。

--allow-net オプションによるネットワークアクセスの制限

github.com

Node.js v20 で Process-based Permission Model という機能が導入されました。 shisama.hatenablog.com

上記の記事で紹介したとおり、すでに --allow-fs-writeオプションなどでファイルシステムなどのアクセスを制限することができますが、--allow-netオプションを使うことでネットワークアクセスも制限できるようになりました。

Node.js の実行時に--allow-netオプションを指定します。

$ node --permission --allow-net index.js

これにより、ネットワークアクセスが許可されます。 --allow-netオプションを指定しない場合、ネットワークアクセスは拒否されます。

以下はhttp://example.comにアクセスしようとした場合の例です。

const http = require("node:http");
// Attempt to bypass the permission
const req = http.get("http://example.com", () => {});

req.on("error", (err) => {
  console.log("err", err);
});

以下のように--permissionオプションのみで実行すると、ネットワークアクセスが拒否され、エラーが発生します。

$ node --permission index.js

err Error: getaddrinfo ERR_ACCESS_DENIED example.com
at lookup (node:dns:234:32)
at emitLookup (node:net:1446:5)
at defaultTriggerAsyncIdScope (node:internal/async_hooks:472:18)
at lookupAndConnectMultiple (node:net:1445:3)
at node:net:1391:7
at defaultTriggerAsyncIdScope (node:internal/async_hooks:472:18)
at lookupAndConnect (node:net:1390:5)
at Socket.connect (node:net:1285:5)
at Object.connect (node:net:245:17)
at Agent.createConnection (node:\_http_agent:240:16) {
errno: undefined,
code: 'ERR_ACCESS_DENIED',
syscall: 'getaddrinfo',
hostname: 'example.com'
}

これにより、意図しないネットワークアクセスを行うことを防止できます。

Web Storage API がフラグなしで利用可能に

github.com

Web Storage API (sessionStorage/localStorage)がフラグなしで利用可能になりました。 developer.mozilla.org Web Storage API は Node.js v22.4.0 以降で利用可能になっていましたが、--experimental-webstorageフラグを付けて実行する必要がありました。 Node.js v25.0.0 からはフラグなしで利用可能になりました。

Web Storage API はグローバルオブジェクトとして提供されるため、import 文や require 文でインポートする必要はありません。

以下は sessionStorage の例です。

// sessionStorage にデータを保存
sessionStorage.setItem("key", "value");

// sessionStorage に保存したデータを取得
let data = sessionStorage.getItem("key");
console.log(data); // 'value'

// sessionStorage に保存したデータを削除
sessionStorage.removeItem("key");
console.log(sessionStorage.getItem("key")); // null

// sessionStorage からすべての保存したデータを削除
sessionStorage.clear();

以下は localStorage の例です。

localStorage.setItem("foo", "bar");
const foo = localStorage.getItem("foo");
console.log(foo); // 'bar'
localStorage.removeItem("foo");
console.log(localStorage.getItem("foo")); // null
localStorage.clear();

localStorage は永続的にデータを保存するため、ファイル名を指定する必要があります。以下の例では、localStorageFileというファイルにデータが保存されます。

$ node --localstorage-file=./localStorageFile index.js

また、Web Storage API を無効にするには --no-webstorageオプションを使用します。
--no-webstorageオプションを指定して実行すると、Web Storage API を使用しようとしたときにエラーが発生します。

$ node --no-webstorage index.js

node:internal/modules/esm/translators:464
    throw new ERR_UNKNOWN_BUILTIN_MODULE(url);
          ^
Error [ERR_UNKNOWN_BUILTIN_MODULE]: No such built-in module: node:storage
    at ModuleLoader.builtinStrategy (node:internal/modules/esm/translators:464:11)
    at #translate (node:internal/modules/esm/loader:564:20)
    at afterLoad (node:internal/modules/esm/loader:614:29)
...

ErrorEvent の追加

github.com

Node.js v25 で ErrorEventクラスが追加されました。 ErrorEventクラスは、イベントエミッターで発生したエラーを表すために使用されます。

developer.mozilla.org

以下のようにEventTargetに対してErrorEventが発生したときに、そのエラー情報を取得できます。

const eventTarget = new EventTarget();
eventTarget.addEventListener("error", (event) => {
  console.log("Message: ", event.error.message);
  console.log("Stack: ", event.error.stack);
  console.log("Name: ", event.error.name);
  console.log("Code: ", event.error.code);
});
const error = new Error("error message");
eventTarget.dispatchEvent(new ErrorEvent("error", { error }));

また独自のカスタムエラーを作成して、ErrorEventで発生させることもできます。

class CustomErrorEvent extends Event {
  constructor(message) {
    super("customerror");
    this.message = message;
  }
}
const eventTarget = new EventTarget();
eventTarget.addEventListener("customerror", function (event) {
  console.error("Message:", event.message);
});
const errorEvent = new CustomErrorEvent("This is a custom error message");
eventTarget.dispatchEvent(errorEvent);
// Message: This is a custom error message

v25 の EOL 予定について

今回紹介した Node.js v25 は 2026 年 6 月でメンテナンスが終了する予定です。 今回紹介した機能は次の v26(2026 年 4 月リリース予定)でも利用可能なので、そちらへ移行するようにしてください。 日程についての最新の情報は以下のリポジトリをご確認ください。

github.com

まとめ

今回は Node.js v25 の主な変更点を紹介しました。
長年の懸案事項だった JSON.stringify の高速化は結構嬉しいのではないでしょうか。fast-json-stringifyといったライブラリもあるぐらいです。
また、--allow-netオプションによるネットワークアクセスの制限もセキュリティ面で便利です。
Web Storage API もフラグなしで利用可能になったので、ブラウザと同じコードが書きやすくなりました。
Web 標準化に向けた取り組みが継続されていたり、他の JavaScript ランタイムの良いところを取り入れたりと、ここ数年の流れに沿った正当なアップデートが続いている印象です。

長くなってしまいましたが、最後までお読みいただきありがとうございました。不備や質問がございましたら、@shisama_までメンションするかブコメなどでコメントください。

参考記事