信頼度ランク
| S | 公式ソース確認済み |
| A | 成功実績多数・失敗例少数 |
| B | 賛否両論 |
| C | 動作未確認・セキュリティリスク高 |
| Z | 個人所感 |
Node.js 20がEOL——2026年4月30日以降はセキュリティパッチなし。Node 22 LTS vs Node 24への移行手順と破壊的変更まとめ
Node.js 20は2026年4月30日に公式サポートを終了。以降はCVEを含む全パッチが停止される。Node 22 LTS(推奨)とNode 24の選択基準、主要な破壊的変更(require(esm)・crypto API削除・V8更新によるネイティブアドオン再ビルド)、AWS Lambda・Vercel・Docker環境での移行手順を解説する。
一言結論
Node.js 20は本日(4月30日)でEOLとなりCVEを含む全パッチが停止。本番環境は即時Node 22 LTSへ移行すべきで、新規プロジェクトはNode 24が最善。最大の注意点はrequire(esm)のデフォルト動作変更とV8エンジン更新によるネイティブアドオン(bcrypt・canvas・sharp等)の再ビルド必須化だ。
なぜ今すぐ動く必要があるか
2026年4月30日、Node.js 20が正式にEnd-of-Life(EOL)を迎えた。
Node.js Release Working Groupは今日以降、Node 20に対してセキュリティパッチを発行しない。つまり今後発見されるすべてのCVEが未修正のまま放置される。
Node.js リリースラインのサポートライフサイクル(2026年5月時点)
Node 18 │▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒│ EOL: 2025年4月
Node 20 │████████████████████│ EOL: 2026年4月30日 ← 本日
Node 22 │████████████████████████████│ Active LTS〜2027年10月
Node 24 │░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│ Active LTS〜2028年4月
Node 22 LTS vs Node 24:どちらに移行すべきか
| 観点 | Node 22 LTS | Node 24 LTS |
|---|---|---|
| LTS移行 | 2024年10月(済み) | 2025年10月(済み) |
| サポート期限 | 2027年10月 | 2028年4月 |
| V8エンジン | 12.4 | 13.6(30%高速) |
| npm | 10.x | 11(65%高速インストール) |
| OpenSSL | 3.3 | 3.5(最新セキュリティデフォルト) |
| TypeScript型ストリッピング | --experimental-strip-types | --strip-typesとして安定化 |
| パーミッションモデル | 試験的 | 本番利用可 |
| エコシステム互換性 | ★★★★★ | ★★★★☆ |
推奨:
- 既存プロジェクト → Node 22 LTS(破壊的変更が少なく最も安全な移行先)
- 新規プロジェクト → Node 24(TypeScript型ストリッピング安定・高速V8・パーミッションモデル)
破壊的変更と対処
1. require() の ESM対応(最重要)
Node 22からrequire()でES Moduleを読み込む実験的サポートが追加された。Node 23でフラグなし動作に変更され、Node 24で安定化している。
// ❌ Node 20まで: この書き方は動かない
const { myFunc } = require('./esm-only-module.mjs');
// ✅ Node 22以降(実験的)/ Node 23以降(フラグなし)
const { myFunc } = require('./esm-only-module.mjs'); // そのまま動く
// ✅ 確実な互換記述: 動的import
const { myFunc } = await import('./esm-only-module.mjs');
影響確認コマンド:
# esm-only パッケージへの依存を確認
node --input-type=module -e "require('./index.js')" 2>&1 | grep "ERR_REQUIRE_ESM"
2. 削除されたCrypto API
Node 22でcrypto.createCipher()とcrypto.createDecipher()が完全削除された。
// ❌ Node 22以降で削除
const cipher = crypto.createCipher('aes192', password);
// ✅ 正しい代替
const key = crypto.scryptSync(password, salt, 24);
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv('aes-192-cbc', key, iv);
検出:
grep -rn "createCipher\b\|createDecipher\b" src/
3. ネイティブアドオンの再ビルド(V8更新)
Node 20(V8 11.3)→ Node 22(V8 12.4)→ Node 24(V8 13.6)でV8 APIが変わるため、ネイティブアドオンは再ビルドが必要だ。
影響を受けやすいパッケージ: bcrypt・canvas・sharp・node-gyp系・DBドライバのネイティブバインディング
# ネイティブアドオンを含むパッケージの確認
npm ls | xargs -I{} sh -c 'ls node_modules/{}/build 2>/dev/null && echo {}'
# 再ビルド
npm rebuild
# または完全クリーン
rm -rf node_modules && npm install
4. url.parse()の段階的削除
url.parse()は非推奨を経て削除に向かっている。WHATWG URL APIへの移行が必要だ。
// ❌ 非推奨(将来削除予定)
const parsed = url.parse('https://example.com/path?q=1');
// ✅ WHATWG URL API
const parsed = new URL('https://example.com/path?q=1');
// parsed.hostname, parsed.pathname, parsed.searchParams.get('q')
環境別の移行手順
ローカル開発(nvm / fnm)
# nvm
nvm install 22 --lts
nvm alias default 22
nvm use 22
# fnm(より高速)
fnm install --lts
fnm default 22
# .nvmrc または .node-version ファイルを更新
echo "22" > .nvmrc
Docker
# ❌ 旧
FROM node:20-alpine
# ✅ 新
FROM node:22-alpine
# または
FROM node:22-slim
# マルチステージビルドの場合は全ステージを更新
FROM node:22-alpine AS builder
FROM node:22-alpine AS runner
AWS Lambda
Node 20のLambdaランタイムは2026年7月31日でAWSがサポート終了予定。Node 22ランタイムに変更する。
# AWS CLI で Lambda のランタイム変更
aws lambda update-function-configuration \
--function-name my-function \
--runtime nodejs22.x
# SAM / Serverless Frameworkの場合
# samconfig.toml または serverless.yml の Runtime を nodejs22.x に変更
Vercel / Netlify
// package.json の engines フィールドを更新
{
"engines": {
"node": ">=22"
}
}
Vercelはpackage.jsonのengines.nodeを参照してランタイムを自動選択する。
GitHub Actions
# ❌ 旧
- uses: actions/setup-node@v4
with:
node-version: '20'
# ✅ 新
- uses: actions/setup-node@v4
with:
node-version: '22'
# またはLTSを追従する場合
node-version: 'lts/*'
移行前の確認チェックリスト
# 1. 現在のNodeバージョン確認
node --version
# 2. 破壊的変更の事前検出
npx node-check-esm . # ESM互換性チェック
# 3. 古い crypto API の使用箇所
grep -rn "createCipher\|createDecipher\|url\.parse\b" src/ --include="*.js" --include="*.ts"
# 4. ネイティブアドオンの確認
npm ls --depth=0 | grep -E "bcrypt|canvas|sharp|sqlite3|serialport"
# 5. テスト実行(新しいNodeで)
nvm use 22 && npm test
Node 24 の注目機能(新規プロジェクト向け)
Node 24(現在LTS、2028年4月まで)を選ぶ理由:
// TypeScript型ストリッピング(--strip-types フラグ安定化)
// node --strip-types index.ts でそのまま実行できる
function greet(name: string): string {
return `Hello, ${name}`;
}
// パーミッションモデル(本番利用可能)
// node --allow-fs-read=./data --allow-net=api.example.com app.js
// WebSocket クライアントがネイティブ対応
const ws = new WebSocket('wss://example.com/socket');
// fs.glob() が標準化
import { glob } from 'fs/promises';
const files = await glob('src/**/*.ts');
落とし穴・注意点
process.binding(): Node 22でいくつかの内部bindingが削除。古いライブラリが依存している場合は要確認- テストランナー: Node 20までの
--experimental-test-reporterが--test-reporterとして安定化。テストスクリプトのフラグを確認 --experimental-*フラグ: Node 20で「実験的」だった機能が変更・削除されている場合がある(--experimental-vm-modules等)- モノリポ環境: ルートの
package.jsonと各パッケージのenginesフィールドを両方更新する
まとめ
Node.js 20は本日でEOLとなり、CVEを含む全パッチが停止した。本番環境での継続使用はセキュリティリスクだ。
- 既存プロジェクト → Node 22 LTSに移行(互換性高く低リスク)
- 新規プロジェクト → Node 24(TypeScript型ストリッピング・パーミッションモデル安定)
- 最大の注意点 → ネイティブアドオンの再ビルドと
require()/ESM動作変更