この記事の要点
• node --watchで自動再起動、--env-fileで環境変数読込
• fs/promises・path・httpが最頻出の組込モジュール
• 新規プロジェクトはESM("type": "module")を推奨
概要
Node.js は V8 JavaScript エンジン上で動作するサーバーサイド JavaScript ランタイムです。非同期 I/O、イベントループ、豊富な組み込みモジュールを提供し、Web サーバー、CLI ツール、ビルドツール、スクリプト自動化など幅広い用途で使われています。本チートシートでは、現行 LTS(v20 / v22)で利用できる主要な API・CLI オプションを整理します。
ECMAScript Modules(ESM, import/export)と CommonJS(require/module.exports)の両方をサポートしますが、新規プロジェクトでは ESM が推奨です。package.json の "type": "module" で切り替えるのが基本的な方法です。
CLI コマンド
実行系
| コマンド | 説明 |
|---|
node script.js | スクリプトを実行 |
node -e "code" | ワンライナーを評価 |
node -p "expr" | 式を評価して結果を出力 |
node --check script.js | 構文チェックのみ |
node --watch script.js | ファイル変更で再実行(v18.11+) |
node --watch-path=src script.js | 監視対象を指定 |
node --env-file=.env script.js | .env を読み込む(v20.6+) |
node --inspect script.js | デバッガを有効化 |
node --inspect-brk script.js | 1行目で停止してデバッグ |
node --test | 組み込みテストランナーを実行(v20+) |
node --version | バージョンを表示 |
実行モード関連オプション
| オプション | 説明 |
|---|
--experimental-vm-modules | ESM の vm モジュールサポート |
--no-warnings | 警告出力を抑制 |
--trace-warnings | 警告のスタックトレースを表示 |
--trace-deprecation | 非推奨警告のスタックトレースを表示 |
--unhandled-rejections=strict | 未処理 Promise 拒否で異常終了 |
--max-old-space-size=4096 | V8 ヒープ上限を MB で指定 |
--enable-source-maps | スタックトレースで source map を解決 |
--prof | V8 プロファイラを有効化 |
--cpu-prof | CPU プロファイルを書き出し |
--heap-prof | ヒーププロファイルを書き出し |
ポイント: --watchフラグで外部ツールなしにホットリロードが可能(v18.11+)。開発時はnode --watch --env-file=.env app.jsが定番です。
モジュールシステム
ESM(推奨)
import fs from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
import path from 'node:path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
export function greet(name) {
return `Hello, ${name}`;
}
export default greet;
CommonJS
const fs = require('node:fs');
const path = require('node:path');
function greet(name) {
return `Hello, ${name}`;
}
module.exports = greet;
module.exports.greet = greet;
動的インポート
| コード | 説明 |
|---|
const mod = await import('./plugin.js'); | モジュールを動的にインポート |
mod.run(); | インポートしたモジュールの関数を実行 |
注意: ESMとCommonJSは混在可能ですが、CJSからESMのrequire()はできません。動的import()を使うか、プロジェクト全体をESMに統一しましょう。
組み込みモジュール接頭辞
公式ドキュメントは node: プレフィックス付き表記を推奨します。これにより npm パッケージとの混同を避けられます。
| コード | 説明 |
|---|
import fs from 'node:fs'; | ファイルシステムモジュールをインポート |
import http from 'node:http'; | HTTPモジュールをインポート |
import path from 'node:path'; | パス操作モジュールをインポート |
組み込みモジュール
fs / fs/promises
| API | 説明 |
|---|
fs.promises.readFile(path, 'utf8') | ファイルを読み込み |
fs.promises.writeFile(path, data) | ファイルを書き込み |
fs.promises.appendFile(path, data) | ファイルに追記 |
fs.promises.mkdir(path, { recursive: true }) | ディレクトリを作成 |
fs.promises.readdir(path, { withFileTypes: true }) | ディレクトリ一覧 |
fs.promises.stat(path) | ファイル情報を取得 |
fs.promises.rm(path, { recursive: true, force: true }) | 削除 |
fs.promises.rename(old, new) | リネーム / 移動 |
fs.promises.cp(src, dest, { recursive: true }) | コピー(v16.7+) |
fs.createReadStream(path) | 読み込みストリーム |
fs.createWriteStream(path) | 書き込みストリーム |
fs.watch(path, listener) | ファイル変更監視 |
実践メモ: fs.promises(async/await)をコールバックAPIより優先しましょう。エラーハンドリングがtry/catchで統一でき、コードが読みやすくなります。
path
| API | 説明 |
|---|
path.join(...segments) | パスを結合 |
path.resolve(...segments) | 絶対パスに解決 |
path.dirname(p) | ディレクトリ部分 |
path.basename(p, ext?) | ファイル名 |
path.extname(p) | 拡張子 |
path.parse(p) | パスを分解 |
path.relative(from, to) | 相対パスを算出 |
path.sep | OS のパス区切り文字 |
process
| API | 説明 |
|---|
process.argv | コマンドライン引数(配列) |
process.env | 環境変数 |
process.cwd() | カレントディレクトリ |
process.chdir(dir) | カレントディレクトリ変更 |
process.exit(code) | プロセス終了 |
process.platform | ’darwin’ / ‘linux’ / ‘win32’ |
process.version | Node.js バージョン |
process.pid | プロセス ID |
process.stdin / stdout / stderr | 標準入出力ストリーム |
process.on('SIGINT', fn) | シグナルハンドラ |
process.nextTick(fn) | 次のティックで実行 |
http / https
import http from 'node:http';
const server = http.createServer((req, res) => {
res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ message: 'ok' }));
});
server.listen(3000, () => {
console.log('Listening on http://localhost:3000');
});
url
| API | 説明 |
|---|
new URL('https://example.com/path?q=1') | URL を解析 |
url.searchParams.get('q') | クエリパラメータを取得 |
url.searchParams.set('q', 'v') | クエリパラメータを設定 |
url.pathname | パス部分 |
url.origin | スキーム + ホスト |
crypto
| コード | 説明 |
|---|
crypto.createHash('sha256').update('hello').digest('hex') | SHA256ハッシュを生成 |
crypto.randomUUID() | UUID v4を生成 |
crypto.randomBytes(16).toString('hex') | ランダムなバイト列を生成 |
events
| コード | 説明 |
|---|
const bus = new EventEmitter(); | イベントエミッターを作成 |
bus.on('message', (data) => console.log(data)); | イベントリスナーを登録 |
bus.emit('message', { text: 'hi' }); | イベントを発火 |
stream
import { pipeline } from 'node:stream/promises';
import { createReadStream, createWriteStream } from 'node:fs';
import { createGzip } from 'node:zlib';
await pipeline(
createReadStream('input.txt'),
createGzip(),
createWriteStream('input.txt.gz'),
);
child_process
import { spawn, execFile } from 'node:child_process';
const ls = spawn('ls', ['-la']);
ls.stdout.on('data', (data) => console.log(data.toString()));
execFile('node', ['--version'], (err, stdout) => {
if (err) throw err;
console.log(stdout);
});
worker_threads
import { Worker, isMainThread, parentPort } from 'node:worker_threads';
if (isMainThread) {
const worker = new Worker(new URL(import.meta.url));
worker.on('message', (m) => console.log('from worker:', m));
} else {
parentPort.postMessage('hello');
}
実用例
1. JSON ファイルを安全に読み書き
import fs from 'node:fs/promises';
async function readJson(path) {
const text = await fs.readFile(path, 'utf8');
return JSON.parse(text);
}
async function writeJson(path, data) {
await fs.writeFile(path, JSON.stringify(data, null, 2) + '\n');
}
2. ディレクトリを再帰的に走査
import fs from 'node:fs/promises';
import path from 'node:path';
async function* walk(dir) {
for (const entry of await fs.readdir(dir, { withFileTypes: true })) {
const full = path.join(dir, entry.name);
if (entry.isDirectory()) yield* walk(full);
else yield full;
}
}
for await (const file of walk('./src')) {
console.log(file);
}
3. 標準入力から1行ずつ読む
import readline from 'node:readline';
const rl = readline.createInterface({ input: process.stdin });
for await (const line of rl) {
console.log('got:', line);
}
4. 環境変数のロード(v20.6+)
| コマンド/コード | 説明 |
|---|
node --env-file=.env app.js | .env ファイルを読み込んで実行 |
console.log(process.env.DATABASE_URL); | 環境変数を参照 |
5. fetch(v18+ で組み込み)
| コード | 説明 |
|---|
const res = await fetch('https://api.example.com/users'); | HTTPリクエストを送信 |
if (!res.ok) throw new Error(\HTTP ${res.status}`);` | レスポンスステータスをチェック |
const users = await res.json(); | レスポンスをJSONとしてパース |
6. AbortController でタイムアウト
const ac = new AbortController();
const timer = setTimeout(() => ac.abort(), 3000);
try {
const res = await fetch(url, { signal: ac.signal });
} finally {
clearTimeout(timer);
}
7. シンプルな HTTP サーバー
import http from 'node:http';
http.createServer(async (req, res) => {
if (req.method === 'GET' && req.url === '/health') {
res.writeHead(200).end('OK');
return;
}
res.writeHead(404).end('Not Found');
}).listen(8080);
8. CLI 引数のパース(標準 util.parseArgs)
import { parseArgs } from 'node:util';
const { values, positionals } = parseArgs({
options: {
name: { type: 'string', short: 'n' },
verbose: { type: 'boolean', short: 'v' },
},
allowPositionals: true,
});
console.log(values, positionals);
9. 組み込みテストランナー
import { test } from 'node:test';
import assert from 'node:assert/strict';
test('1 + 2 = 3', () => {
assert.equal(1 + 2, 3);
});
node --test
10. 終了時のクリーンアップ
| コード | 説明 |
|---|
function shutdown() { console.log('shutting down...'); process.exit(0); } | シャットダウン処理を定義 |
process.on('SIGINT', shutdown); | SIGINT シグナルを受信 (Ctrl+C) |
process.on('SIGTERM', shutdown); | SIGTERM シグナルを受信 |
11. ストリームでの巨大ファイル処理
import { createReadStream } from 'node:fs';
import { createInterface } from 'node:readline';
const rl = createInterface({ input: createReadStream('huge.log') });
let count = 0;
for await (const line of rl) {
if (line.includes('ERROR')) count++;
}
console.log('errors:', count);
12. 非同期処理の並列制御
| コード | 説明 |
|---|
const results = await Promise.all(urls.map((u) => fetch(u).then((r) => r.json()))); | 複数のPromiseを並列で実行 |
13. パフォーマンス計測
| コード | 説明 |
|---|
const t0 = performance.now(); | 計測開始時刻を記録 |
console.log('took', performance.now() - t0, 'ms'); | 経過時間を表示 |
14. EventEmitter で once を Promise 化
| コード | 説明 |
|---|
import { once } from 'node:events'; | once ヘルパーをインポート |
const [data] = await once(emitter, 'data'); | イベントを一度だけ待機 |
15. ファイルから JSON Lines を読む
import { createReadStream } from 'node:fs';
import { createInterface } from 'node:readline';
const rl = createInterface({ input: createReadStream('events.jsonl') });
for await (const line of rl) {
if (!line.trim()) continue;
const event = JSON.parse(line);
console.log(event.type);
}
npm スクリプト連携
{
"type": "module",
"scripts": {
"start": "node src/index.js",
"dev": "node --watch --env-file=.env src/index.js",
"test": "node --test",
"lint": "eslint .",
"build": "node scripts/build.js"
}
}
よく使うオプション早見表
| オプション | 用途 |
|---|
--watch | ファイル変更で自動再起動 |
--env-file=<path> | .env 読み込み |
--test | テストランナー実行 |
--inspect[=host:port] | デバッガ有効化 |
--enable-source-maps | source map 解決 |
--max-old-space-size=N | ヒープ上限 (MB) |
--experimental-fetch | (v18 未満)fetch 有効化 |
--require <module> | 起動時にモジュール読み込み(CJS) |
--import <module> | 起動時に ESM 読み込み |
--no-deprecation | 非推奨警告を抑制 |
ポイント: node:プレフィックス(import fs from 'node:fs')を付けるとnpmパッケージと組込モジュールの混同を防げます。
注意: process.exit()は書き込み中のストリームを切断します。グレースフルシャットダウンにはSIGTERMハンドラで後処理してからexitしましょう。
トラブルシューティング
| 症状 | 原因と対処 |
|---|
ERR_REQUIRE_ESM | CJS から ESM を require している。動的 import() を使うか ESM 化する |
Cannot use import statement outside a module | package.json に "type": "module" を追加する |
EADDRINUSE | ポートが既に使用中。lsof -i :PORT で確認して停止 |
ENOENT | パスが存在しない。path.resolve で絶対パス化して確認 |
MaxListenersExceededWarning | EventEmitter のリスナー過多。emitter.setMaxListeners(n) |
UnhandledPromiseRejection | await し忘れ。--unhandled-rejections=strict で検出 |
| メモリ不足 | --max-old-space-size=4096 で上限引き上げ |
| 非同期スタックが切れる | --enable-source-maps と --async-stack-traces を確認 |
Tips & ベストプラクティス
- 新規プロジェクトは ESM (
"type": "module") を選択し、node: プレフィックスで標準モジュールを import する。
fs.promises を使い、コールバック API より async/await を優先する。
- LTS バージョンを使う。
nvm や volta、fnm でバージョン管理する。
- 環境変数は
--env-file=.env を活用し、dotenv への依存を減らす。
- HTTP クライアントは標準
fetch で十分なケースが多い。タイムアウトは AbortSignal.timeout(ms) で簡潔に書ける。
- テストは
node --test で外部依存なしに開始できる。
- パフォーマンスが必要な箇所は
worker_threads を検討する。CPU バウンド処理を別スレッドへ。
process.exit() を多用しない。書き込み中ストリームを切るとデータ欠落が起こる。
- 例外は
process.on('uncaughtException') ではなく、各境界で try/catch して構造化ログに残す。
- 依存ツリーは
npm ls や npm audit で定期的に確認する。
参考リソース
この技術を体系的に学びたいですか?
未来学では東証プライム上場企業のITエンジニアが24時間サポート。月額24,800円から、退会金0円のオンラインIT塾です。
メールで無料相談する
← 一覧に戻る