Node.js

Chrome V8 エンジン上で動作するサーバーサイド JavaScript ランタイム

JavaScriptランタイム

Node.js とは

Node.js は、Chrome の V8 JavaScript エンジンをベースにしたサーバーサイドランタイムである。2009 年に Ryan Dahl が開発し、ノンブロッキング I/O とイベントループによる高い並行処理性能が特徴。AWS Lambda のデフォルトランタイムの 1 つでもある。

シングルスレッド + イベントループ

Node.js はシングルスレッドだが、イベントループとノンブロッキング I/O で大量の同時接続を処理する。

リクエスト → イベントループ → I/O 操作 (非同期) → コールバック → レスポンス
                ↑                                    |
                └────────────────────────────────────┘

CPU バウンドな処理 (画像変換、暗号計算) はイベントループをブロックするため、Worker Threads や外部サービスに委譲する。

Node.js vs Deno vs Bun

観点 Node.js Deno Bun
エンジン V8 V8 JavaScriptCore
パッケージ npm URL import / npm npm
TypeScript トランスパイル必要 ネイティブ対応 ネイティブ対応
セキュリティ 制限なし パーミッション制御 制限なし
エコシステム 最大 成長中 成長中

Node.js の最大の強みはエコシステムの規模。npm には 200 万以上のパッケージがあり、ほぼあらゆるユースケースにライブラリが存在する。

Lambda での Node.js

Lambda は Node.js ランタイムを公式サポートしており、コールドスタートが軽量 (Python と並んで最速クラス)。

観点 Node.js Python Java
コールドスタート 100〜300ms 100〜300ms 1〜5s
実行速度 高速 中程度 高速
メモリ効率 良好 良好 大きい

CommonJS vs ES Modules

// CommonJS (従来)
const fs = require('fs');
module.exports = { handler };

// ES Modules (推奨)
import { readFile } from 'fs/promises';
export const handler = async (event) => { /* ... */ };

Lambda は ES Modules をサポートしており、package.json"type": "module" を指定するか、ファイル拡張子を .mjs にする。

よくある落とし穴

  • イベントループのブロック: JSON.parse で巨大な JSON を処理すると他のリクエストが待たされる
  • メモリリーク: クロージャやグローバル変数にデータを蓄積し続けると Lambda の実行環境が肥大化する
  • コールバック地獄: async/await を使わずにコールバックをネストすると可読性が崩壊する
  • node_modules の肥大化: Lambda のデプロイパッケージが 250MB 制限に達する。Lambda Layer や Tree Shaking で対策する

関連書籍も参考になる。

関連用語