SJ blog
backend
S

信頼度ランク

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 LTSNode 24 LTS
LTS移行2024年10月(済み)2025年10月(済み)
サポート期限2027年10月2028年4月
V8エンジン12.413.6(30%高速)
npm10.x11(65%高速インストール)
OpenSSL3.33.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が変わるため、ネイティブアドオンは再ビルドが必要だ。

影響を受けやすいパッケージ: bcryptcanvassharpnode-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.jsonengines.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動作変更

参考リンク