2026 年 10 月 28 日、Node.js 26 が LTS(長期サポート版)になりました。コードネームは「Lithium」です。Node.js の公式サイトは「本番のアプリケーションは Active LTS か Maintenance LTS だけを使うべき」としており、26 はこの日から本番で選べる版になりました。
この記事は、Node.js を使う案件を保守しているエンジニアに向けて書いています。Next.js などのフロントエンドのビルド環境、API サーバー、バッチ処理などです。担当しているプロジェクトを 26 に上げるか、いつ上げるかを決めて、移行前に確かめることを一覧にできる状態を目指します。内容は 2026 年 11 月 7 日時点の公式情報にもとづきます。
各バージョンのサポート期限と、移行を急ぐべき案件
まず、いま使われている主なバージョンの期限を確かめます。日付は Node.js の Release リポジトリにある予定表のものです。
| バージョン | コードネーム | いまの状態 | Maintenance への移行 | サポート終了(EOL) |
|---|---|---|---|---|
| 20 | Iron | 終了済み | ― | 2026 年 4 月 30 日 |
| 22 | Jod | Maintenance LTS | 2025 年 10 月 21 日 | 2027 年 4 月 30 日 |
| 24 | Krypton | Maintenance LTS | 2026 年 10 月 20 日 | 2028 年 4 月 30 日 |
| 26 | Lithium | Active LTS | 2027 年 10 月 20 日 | 2029 年 4 月 30 日 |
| 27 | ― | Alpha | ― | 2030 年 4 月 30 日(予定) |
Active LTS は、Release チームが確かめた新機能・バグ修正・更新が入る段階です。Maintenance は、重大なバグ修正とセキュリティ修正だけが入る段階です。24 は 10 月 20 日に Maintenance に入ったので、これから新しい機能が入るのは 26 です。
この表から、急ぐ順番が決まります。
- 20 で動いている案件:すでにサポートが切れています。公式のセキュリティリリースの告知には「サポートが終わった版は、セキュリティリリースのたびに必ず影響を受ける」とあります。最優先で上げてください。
- 22 の案件:残りは約半年です。年内に計画を立て、年明けから作業する流れが現実的です。行き先は 24 ではなく 26 をおすすめします。24 の終了は 2028 年 4 月で、26 より 1 年早いからです。
- 24 の案件:2028 年 4 月まで時間があります。急ぐ必要はありませんが、新しく始める案件は 26 で始めると、次の移行までの期間を長く取れます。
なお、11 月 11 日(またはその直後)に 26・24・22 のセキュリティリリースが予告されています。最も高い深刻度は High です。どのバージョンを使っていても、パッチ版の更新は予定に入れておきましょう。
22・24 から上げるときに影響する変更
24 から 26 に上げる場合、間にある 25 の破壊的変更もまとめて受けます。22 からならさらに 23 の変更も加わります。ここでは、受託開発の案件で影響が出やすいものに絞って並べます。
| 変更 | 入った版 | 影響しやすい場面 |
|---|---|---|
| Corepack が同梱されなくなった | 25 | corepack enable で pnpm や Yarn を用意している CI・Dockerfile |
fs.F_OK などの定数が削除 |
25 | 古いコードや依存パッケージのファイル存在チェック |
SlowBuffer が削除 |
25 | 古い依存パッケージ |
http の writeHeader() が削除 |
26 | 古いサーバーのコード。writeHead() に置き換える |
_stream_readable などの内部モジュールが削除 |
26 | require('_stream_readable') をしている古いパッケージ |
NODE_MODULE_VERSION が 147 に |
26 | ネイティブアドオン(画像処理・暗号・DB ドライバなど) |
--experimental-transform-types が削除 |
26 | TypeScript の enum などを Node.js で直接動かしていた場合 |
module.register() が実行時に非推奨 |
26 | 独自のローダーを使っているテストやツール |
| Linux 版のバイナリが libatomic に依存 | 25 | 最小構成の Docker イメージや独自のサーバー |
それぞれ補足します。
Corepack:25 のリリースノートに「build: stop distributing Corepack」とあります。これまで Node.js に付いてきたので、corepack enable を書くだけで pnpm が使えていました。26 ではこの行が「コマンドが見つからない」で失敗します。npm で Corepack を別に入れるか、pnpm の公式の入れ方に切り替える必要があります。CI の設定ファイルと Dockerfile を corepack で検索してください。
ネイティブアドオン:C++ で書かれた拡張は、ビルドしたときの NODE_MODULE_VERSION と一致しないと読み込めません。sharp や bcrypt、各種 DB ドライバなどが当たります。多くは node_modules を消して入れ直せば済みます。ただし、古い版のまま固定していて 26 向けのバイナリがない場合は、パッケージの更新が必要です。
libatomic:26.13.0 のリリースノートは「Node.js 25 から、Linux の公式バイナリは libatomic にリンクしている。ディストリビューションによっては別にインストールが必要」と注意しています。公式の Docker イメージではなく、最小構成のイメージに公式バイナリを置いている場合は、起動しないことがあります。
TypeScript:Node.js は .ts ファイルから型を取り除いて、そのまま実行できます。この型ストリップは 24.12.0 と 25.2.0 で「安定版」になりました。一方で、enum のように JavaScript のコードへの変換が必要な書き方を動かすための --experimental-transform-types は、26 で削除されました。代わりのフラグは用意されていません。このフラグで enum を動かしていたなら、as const のオブジェクトなどに書き換えるか、ビルドしてから実行する形に戻します。
移行の手順:固定している場所を洗い出して CI で確かめる
移行の作業で一番漏れやすいのは、Node.js のバージョンを指定している場所です。手元の開発環境だけ 26 にして、本番は 22 のまま、ということが起きます。まず、プロジェクトの中を検索して一覧にします。
# バージョンを指定していそうなファイルと記述を探す
git grep -nE 'node-version|engines|FROM node|nodejs[0-9]+|corepack' -- \
'*.yml' '*.yaml' 'Dockerfile*' 'package.json' '.nvmrc' '.node-version' '.tool-versions'
よく出てくるのは次の場所です。
.nvmrc・.node-version・.tool-versions(開発者の手元)package.jsonのengines(npm の警告や、ホスティングのバージョン選択)- GitHub Actions の
actions/setup-nodeのnode-version - Dockerfile の
FROM node:22-... - ホスティングやサーバーレスの管理画面・設定ファイルで選んでいるランタイム
管理画面で選ぶものは、リポジトリを検索しても出てきません。案件ごとに、どのサービスでどう選んでいるかを控えておきましょう。各サービスが 26 をいつから選べるようにしたかは、サービスによって異なります。必ずそれぞれの公式ドキュメントで確かめてください。
次に、CI で今の版と 26 を並べてテストします。両方で通ることを確かめてから切り替えると、問題の切り分けが楽になります。
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [22, 26]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm ci
- run: npm test
- run: npm run build
テストを走らせるときは、非推奨の警告も見ます。26 で実行時に非推奨になったものは、今は動いても次の版で消える可能性があります。次のように実行すると、警告がどこから出ているかを調べられます。
# 非推奨の警告を、呼び出し元のスタックトレース付きで表示する
node --trace-deprecation dist/server.js
# 非推奨の API を使った時点でエラーにして、漏れなく見つける
node --throw-deprecation dist/server.js
警告の番号(DEP0205 など)は、公式の非推奨 API 一覧で意味と置き換え先を引けます。たとえば DEP0205 は module.register() で、置き換え先として module.registerHooks() が示されています。
すべて通ったら、手元・CI・Docker・本番の順に指定を 26 に揃えます。package.json の engines も更新しておきます。
{
"engines": {
"node": ">=26"
}
}
26 で使えるようになった書き方
移行の手間だけでなく、上げることで書きやすくなる点もあります。案件のコードで使いどころがありそうなものを 3 つ紹介します。
Temporal が既定で使える
26 では、日付と時刻を扱う新しい API の Temporal が、フラグなしで使えるようになりました。従来の Date は、月が 0 から始まるなど間違いやすく、多くの案件で日付ライブラリを入れてきました。Temporal は、日付だけ・日時・タイムゾーン付きの日時を、別の型として扱えます。
// 今日の日付(タイムゾーンを持たない「日付だけ」の値)
const today = Temporal.Now.plainDateISO();
// 30 日後の締め切り。月の長さは自動で考慮される
const deadline = today.add({ days: 30 });
console.log(today.toString()); // 例: 2026-11-07
console.log(deadline.toString()); // 例: 2026-12-07
「日付だけ」を扱う処理で、時差のずれが起きにくくなります。ただし、使うのはサーバー側に限ってください。ブラウザで動くコードでは、利用者のブラウザが Temporal に対応しているかを別に確かめる必要があります。
Map の「なければ入れる」が 1 行に
V8 が 14.6 に上がり、Map.prototype.getOrInsert() と getOrInsertComputed() が入りました。集計でよく書く「キーがなければ初期値を入れてから取り出す」処理が短くなります。
const ordersByCustomer = new Map();
for (const order of orders) {
// これまで: if (!map.has(id)) map.set(id, []); map.get(id).push(order);
ordersByCustomer.getOrInsert(order.customerId, []).push(order);
}
// 初期値を作る処理が重いときは、必要なときだけ関数を呼ぶ版を使う
const cache = new Map();
const report = cache.getOrInsertComputed(month, (key) => buildReport(key));
getOrInsert() は、渡した初期値を毎回作ってしまいます。重い処理の結果を入れたいときは getOrInsertComputed() を選びます。
TypeScript を直接実行する
型ストリップは安定版になり、ビルドスクリプトや管理用の小さなツールなら、.ts をそのまま node で動かせます。型の検査はしないので、検査は tsc --noEmit を CI で別に回します。公式ドキュメントは、TypeScript 5.8 以降と次の設定を勧めています。
{
"compilerOptions": {
"noEmit": true,
"target": "esnext",
"module": "nodenext",
"rewriteRelativeImportExtensions": true,
"erasableSyntaxOnly": true,
"verbatimModuleSyntax": true
}
}
erasableSyntaxOnly を入れると、enum のように Node.js が取り除けない書き方を、エディタの段階でエラーにできます。前の節で触れた --experimental-transform-types の削除に、先回りして備えられます。なお、.tsx ファイルや、tsconfig の paths による別名の import は対象外です。React のコードやパスの別名を使うアプリ本体は、これまでどおりビルドして動かします。
Node.js 27 からのリリーススケジュールの変化
26 は、これまでのリリースの決まりで出る最後の版です。27 からは、メジャーバージョンが年 1 回になります。
これまでは、4 月に偶数、10 月に奇数の版が出ていました。偶数だけが LTS になり、奇数は半年でサポートが終わっていました。新しい決まりでは、すべての版が次の順に進みます。
Alpha は、破壊的変更を早めに試すための段階です。対象はライブラリの作者や CI での互換性テストで、本番向けではないとされています。27 では、Alpha が 2026 年 10 月に始まり、27.0.0 が 2027 年 4 月に出て、2027 年 10 月に LTS になる予定です。Release リポジトリの説明では、27 以降は 30 か月の LTS 期間ずっと Active LTS のままで、Maintenance の段階を通りません。公式は、この予定はまだ変わる可能性があるとしています。
案件の計画で効いてくるのは、次の 2 点です。
- バージョン選びが単純になる:「偶数を選ぶ」という決まりがなくなり、LTS に入った最新の版を選べばよくなります。
- 移行は 1 年ごとの作業になる:新しい LTS が毎年 10 月に出ます。保守契約で年に 1 回、10〜12 月に Node.js の更新を予定に入れておくと、サポート切れに追われずに済みます。
まとめ
- Node.js 26 は 2026 年 10 月 28 日に LTS になり、2029 年 4 月末までサポートされます。22 は 2027 年 4 月末で終わるので、今が移行を計画する時期です。行き先は 24 より 26 が有利です。
- 24 から上げる場合も、25 の変更(Corepack の同梱終了、削除された API、libatomic)をまとめて受けます。バージョンを指定している場所を洗い出し、CI で今の版と 26 を並べて確かめてから切り替えてください。
- 27 からは年 1 回のリリースになり、すべての版が LTS になります。毎年秋に Node.js の更新を予定に入れておくのがおすすめです。
次に読むとよいのは、26.0.0 のリリースノートの破壊的変更の一覧です。