Node.jsチートシート - CLI・Module・fs・HTTP

8分 で読める | 2026.04.10

公式ドキュメント

Node.jsはbrowser外でJavaScriptを実行するruntimeです。productionではNode.js公式release表を確認し、support中のLTSを使います。

最頻出10項目

操作
file実行node app.js
script実行npm run dev
version確認node --version
syntax確認node --check app.js
watch実行node --watch app.js
環境変数filenode --env-file=.env app.js
ESM importimport fs from "node:fs"
file読込readFile(path, "utf8")
HTTP servercreateServer(handler)
testnode --test

CLI

node app.js
node --watch app.js
node --inspect app.js
node --check app.js
node --test
node --env-file=.env app.js

--inspectはdebug portを開きます。共有networkへ無条件に公開しないでください。.envにはsecretが含まれるためGitへcommitせず、productionではplatformのsecret管理を使います。

command line argumentはprocess.argvから読みます。

const [, , name = "Ada"] = process.argv;
console.log(`Hello, ${name}`);

複雑なCLIではnode:utilparseArgsを使えます。

ES Modules

新規projectではESMを基準にできます。

{
  "type": "module",
  "scripts": {
    "dev": "node --watch src/index.js",
    "start": "node src/index.js",
    "test": "node --test"
  }
}
// math.js
export function add(left, right) {
  return left + right;
}
import { add } from "./math.js";

console.log(add(2, 3));

relative importではfile extensionを書きます。組み込みmoduleはnode:接頭辞を付けると明確です。

import path from "node:path";
import { fileURLToPath } from "node:url";

const filename = fileURLToPath(import.meta.url);
const dirname = path.dirname(filename);

CommonJS

const fs = require("node:fs");
module.exports = { fs };

.cjsまたは"type": "commonjs"で扱います。ESMとCommonJSを混在させる場合はpackageのexportsと対象runtimeをtestします。

fs/promises

import {
  mkdir,
  readFile,
  writeFile,
} from "node:fs/promises";

await mkdir("./data", { recursive: true });

const config = JSON.parse(
  await readFile("./config.json", "utf8"),
);

await writeFile(
  "./data/output.json",
  JSON.stringify(config, null, 2),
  "utf8",
);

writeFileは既存fileを上書きします。重要dataでは一時fileへ書いてrenameする方法、backup、同時writeの制御を検討します。pathをuser inputから受け取る場合は、許可directory外へ出ないよう検証します。

よく使うAPI

API用途
readFilefile全体を読む
writeFilefile全体を書く
appendFile末尾へ追記
mkdirdirectory作成
readdirdirectory一覧
statfile情報
rename名前変更・移動
rmfile・directory削除

rm({ recursive: true })は破壊的です。空文字、workspace root、home directoryを対象にしないよう、削除前に解決済みpathを表示・検証してください。

path

import path from "node:path";

const file = path.join("data", "users.json");
const absolute = path.resolve(file);
const extension = path.extname(file);
const base = path.basename(file);

path文字列を"/"で連結せずpath.joinを使うとOS差を扱いやすくなります。URL pathの操作にはURLを使い、filesystem pathと混ぜません。

processと環境変数

const port = Number(process.env.PORT ?? "3000");

if (!Number.isInteger(port)) {
  throw new Error("PORT must be an integer");
}

console.log({
  pid: process.pid,
  platform: process.platform,
  cwd: process.cwd(),
});

環境変数はすべてstringまたはundefinedです。number・booleanへ変換し、起動時に必須値を検証します。secretをlogへ出しません。

終了codeは成功が0、失敗は通常0以外です。

try {
  await main();
} catch (error) {
  console.error(error);
  process.exitCode = 1;
}

cleanupを待たず即終了するprocess.exit()より、exitCodeを設定する方法を基本にします。

HTTP server

import { createServer } from "node:http";

const server = createServer((request, response) => {
  if (request.method === "GET" && request.url === "/health") {
    response.writeHead(200, {
      "content-type": "application/json; charset=utf-8",
    });
    response.end(JSON.stringify({ status: "ok" }));
    return;
  }

  response.writeHead(404, {
    "content-type": "application/json; charset=utf-8",
  });
  response.end(JSON.stringify({ error: "not_found" }));
});

server.listen(3000, "127.0.0.1");

request bodyにはsize上限を設け、timeout、method、content-type、validationを確認します。Internet公開にはTLS、reverse proxy、logging、graceful shutdownなども必要です。

fetch

const response = await fetch("https://api.example.com/users", {
  signal: AbortSignal.timeout(5000),
  headers: {
    accept: "application/json",
  },
});

if (!response.ok) {
  throw new Error(`HTTP ${response.status}`);
}

const users = await response.json();

fetchは404や500だけではrejectしないためresponse.okを確認します。tokenをsource codeやerror messageへ入れません。

JSON

import { readFile } from "node:fs/promises";

async function readJson(file) {
  const text = await readFile(file, "utf8");
  return JSON.parse(text);
}

JSON.parseはsyntax errorをthrowします。外部dataはparse後にschema validationします。

EventとStream

大きなfileを全体読込せずstreamで処理できます。

import { createReadStream } from "node:fs";
import { createGzip } from "node:zlib";
import { pipeline } from "node:stream/promises";

await pipeline(
  createReadStream("input.log"),
  createGzip(),
  process.stdout,
);

pipelineはerror伝播とstream終了をまとめます。binary dataを文字列として扱わないようencodingを確認します。

Test

import assert from "node:assert/strict";
import test from "node:test";

test("add", () => {
  assert.equal(2 + 3, 5);
});
node --test
node --test --test-name-pattern="add"

利用可能optionは使用中のNode.js versionのCLI referenceを確認してください。

npm scripts

{
  "scripts": {
    "dev": "node --watch src/index.js",
    "start": "node src/index.js",
    "test": "node --test",
    "check": "node --check src/index.js"
  }
}

dependency installではlockfileをcommitし、CIではnpm ciを使います。install scriptを含むdependencyは、実行内容と供給chain riskを確認します。

Abortと並列処理

独立した非同期処理はPromise.allでまとめられます。1つがrejectすると全体もrejectします。

const [user, settings] = await Promise.all([
  fetchUser(),
  fetchSettings(),
]);

大量のfileやURLへ無制限に同時requestを送らず、同時実行数を制限します。timeoutやcancelに対応するAPIではAbortSignalを渡します。

const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), 5000);

try {
  await fetch("https://example.com/", {
    signal: controller.signal,
  });
} finally {
  clearTimeout(timer);
}

AbortSignal.timeout()を利用できるNode.js versionでは短く書けます。対象versionのAPI referenceを確認してください。

Graceful shutdown

function shutdown(signal) {
  console.log(`received ${signal}`);

  server.close((error) => {
    if (error) {
      console.error(error);
      process.exitCode = 1;
    }
  });
}

process.once("SIGTERM", shutdown);
process.once("SIGINT", shutdown);

新規requestの受付を止め、処理中request、DB connection、queueを終了してからprocessを閉じます。強制終了までのtimeoutは実行platformの猶予より短く設定します。

トラブル確認

node --version
npm --version
node -p "process.execPath"
node -p "process.cwd()"
npm ls
  • ERR_MODULE_NOT_FOUND: path、extension、package exportsを確認
  • require is not defined: ESMでCommonJS構文を使っていないか確認
  • EADDRINUSE: 同じportを別processが使用
  • EACCES: file・port権限を確認
  • unhandled rejection: awaitとerror handlingを確認

高度なWorker、child process、stream変換、暗号、production server設計は必要なmoduleの公式documentへ進んでください。

参考リソース

← 一覧に戻る
PR
PR
PR
PR