Contents
1. Node.js 20 のインストール
1‑1. 公式インストーラでの導入
| OS | ダウンロード先 | 手順 |
|---|---|---|
| Windows | https://nodejs.org/en/download → Windows Installer (.msi) | インストーラを実行し、画面指示に従うだけで完了 |
| macOS | 同上 → macOS Installer (.pkg) | .pkg を開き、標準インストール手順へ |
| Linux | 同上 → 各ディストリビューション向けバイナリ or tar.gz | tar -xJf node-v20.x.x-linux-x64.tar.xz && sudo cp -r node‑v20.x.x‑linux‑x64/{bin,include,lib,share} /usr/ など |
インストール後は以下でバージョンを確認できます。
|
1 2 3 |
node -v # => v20.x.x npm -v # npm のバージョンも同時に表示 |
1‑2. nvm (Node Version Manager) を用いたマルチバージョン管理
|
1 2 3 4 5 6 7 8 9 10 11 12 |
# nvm 本体のインストール(2024 年現在の最新版 v0.39.7) curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash # シェルを再起動 → nvm が認識されたことを確認 command -v nvm # => nvm # Node.js 20 系列の最新安定版を取得 nvm install 20 # カレントシェルで使用するバージョンを切り替え nvm use 20 |
nvm ls でインストール済みバージョン一覧、nvm alias default 20 でデフォルトを設定できます。
2. トップレベル await の前提条件
2‑1. ESモジュール (ESM) が必須
トップレベルで await を記述できるのは ECMAScript 2022 以降で標準化された ESモジュール のみです。設定方法は大きく二通りあります。
| 設定 | 内容 | 推奨シーン |
|---|---|---|
package.json に "type": "module" を追加 |
.js 拡張子でも ESM として扱われる |
プロジェクト全体で ESモジュール化したい場合 |
ファイル拡張子を .mjs に変更 |
明示的に ESM と判定される | 既存の CommonJS コードと混在させたいとき |
|
1 2 3 4 5 6 7 8 |
// package.json の一例 { "type": "module", "scripts": { "start": "node index.js" } } |
2‑2. 標準化された根拠
- ECMAScript 2022(第13版): https://tc39.es/ecma262/#sec-modules-top-level-await
- Node.js 20 のリリースノートでも「トップレベル await は実験フラグ不要でデフォルト有効」と明記されています(https://nodejs.org/en/blog/release/v20.0.0/)。
3. 実装例:TLA を使った非同期コード
以下は ESM 前提で書かれたサンプルです。すべて await がモジュール評価時に実行される点に注意してください。
3‑1. axios + HTTP GET
|
1 2 |
npm i axios |
|
1 2 3 4 5 6 |
// file: fetchData.mjs import axios from "axios"; const response = await axios.get("https://api.example.com/data"); console.log(response.data); |
3‑2. 標準 fetch API(Node.js 20 内蔵)
|
1 2 3 4 5 6 7 8 9 |
// file: getUsers.mjs const res = await fetch("https://api.example.com/users"); if (!res.ok) { throw new Error(`HTTP ${res.status}`); } const users = await res.json(); console.log(users); |
3‑3. fs.promises による設定ファイル読み込み
|
1 2 3 4 5 6 7 |
// file: loadConfig.mjs import { readFile } from "fs/promises"; const raw = await readFile("./config.json", "utf8"); const config = JSON.parse(raw); console.log(config); |
ポイント:TLA により
async関数でラップする必要がなく、コードがフラットになる一方で「モジュールのロード自体がブロック」されるため、重い I/O は別モジュールに切り出す設計が推奨されます。
4. エラーハンドリングと CommonJS 代替策
4‑1. TLA 環境での例外捕捉
|
1 2 3 4 5 6 7 |
try { const data = await fetchData(); // 任意の非同期関数呼び出し console.log(data); } catch (err) { console.error("取得失敗:", err); } |
await の直前に try が無い場合、モジュール評価時の例外はプロセス全体を終了させる可能性があります。
4‑2. CommonJS で同様の非同期処理を書く方法
CommonJS (require) ではトップレベル await が使えないため、即時非同期関数 (IIFE) を利用します。
|
1 2 3 4 5 6 7 8 9 10 11 |
// file: cjs-example.js // ← .cjs または package.json に "type":"commonjs" (async () => { try { const res = await fetch("https://api.example.com"); const json = await res.json(); console.log(json); } catch (e) { console.error(e); } })(); |
| 手法 | メリット | デメリット |
|---|---|---|
| ESM の TLA | コードが平坦で可読性向上 | モジュール評価時に待機が入る |
| CommonJS IIFE | 既存 CJS プロジェクトでも非同期処理可能 | 関数スコープが増え、変数のスコープ管理がやや煩雑 |
5. 実務導入のベストプラクティス
5‑1. package.json とツールチェーンの整備
|
1 2 3 4 5 6 7 8 9 10 11 12 |
{ "type": "module", "scripts": { "test": "node --test", "start": "node index.mjs" }, "devDependencies": { "eslint": "^8.57.0", "jest": "^29.7.0" } } |
- ESLint:
parserOptions.sourceTypeを"module"に設定。 - Jest (v29+) はデフォルトで ESM に対応しているので、テストファイルは
.mjsまたはtype:"module"のプロジェクトでそのまま使用可能です。
5‑2. パフォーマンス上の留意点
- モジュール評価時の待機
- 重い I/O(例: 大量ファイル読み込み、外部 API 呼び出し)は別モジュールに切り出すか
Promise.allで同時実行させる。 - 測定手法
js
console.time("fetch");
const data = await fetch(...);
console.timeEnd("fetch"); // 所要時間をコンソールに出力 - デバッグ
node --inspect-brk ./index.mjsで VS Code のデバッガに接続し、ステップ実行が可能。--trace-async-hooksオプションは非同期フローの可視化に有用です。
5‑3. フラグ不要の確認
Node.js 20 は 標準でトップレベル await をサポート しています。過去に必要だった --experimental-modules や --no-warnings といったフラグは一切使用しません。
6. まとめ
| 項目 | 要点 |
|---|---|
| インストール | 公式サイトのインストーラか nvm が最もシンプル。 node -v でバージョン確認。 |
| TLA の前提 | ESモジュール (type:"module" or .mjs) が必須。ECMAScript 2022 に正式採用。 |
| 実装例 | axios・fetch・fs.promises を TLA で記述するとコードが平坦化。 |
| エラーハンドリング | try / catch が基本。CommonJS は IIFE パターンで代替。 |
| 実務導入 | package.json に "type":"module"、ESLint/Jest の設定を整える。モジュール評価の待機に注意し、必要なら処理分割や Promise.all で最適化。 |
| デバッグ・計測 | 標準デバッガ (--inspect-brk) と console.time 系でボトルネックを特定できる。 |
Node.js 20 環境において、トップレベル await を正しく設定すれば 非同期ロジックが直感的かつ安全に記述可能 です。本稿の手順とベストプラクティスを参考に、開発フローへスムーズに取り入れてください。