Node.jsは、JavaScriptをサーバーサイドで実行するためのランタイム環境です。2009年にRyan Dahlによって開発されて以来、Node.jsはWebアプリケーション開発の風景を一変させました。本記事では、Node.jsの基本概念から実際のインストール、REPL操作までを体系的に解説します。
実行環境
| 項目 | バージョン |
|---|---|
| Node.js | 20.x LTS以上 |
| npm | 10.x以上 |
| OS | Windows/macOS/Linux |
前提条件
- JavaScriptの基礎文法を理解していること
- コマンドライン(ターミナル)の基本操作ができること
Node.jsとは
Node.jsは、オープンソースかつクロスプラットフォームのJavaScriptランタイム環境です。Google ChromeのV8 JavaScriptエンジンをベースに構築されており、ブラウザ外でJavaScriptを実行できます。
graph TD
A[JavaScript コード] --> B[Node.js ランタイム]
B --> C[V8 エンジン]
B --> D[libuv]
C --> E[JavaScript 実行]
D --> F[非同期I/O]
D --> G[イベントループ]
D --> H[スレッドプール]Node.jsは単一プロセスで動作し、リクエストごとに新しいスレッドを作成しません。標準ライブラリで提供される非同期I/Oプリミティブにより、JavaScriptコードがブロッキングすることを防ぎます。
Node.jsの歴史と設計思想
誕生の背景
2009年、Ryan DahlはJSConf EUでNode.jsを発表しました。当時のサーバーサイド開発では、ApacheのようなWebサーバーがリクエストごとにスレッドを生成する「スレッドベース」のモデルが主流でした。しかし、このモデルには以下の課題がありました。
- 大量の同時接続でメモリ消費が増大する
- スレッド間のコンテキストスイッチによるオーバーヘッド
- デッドロックや競合状態などの並行処理の複雑さ
Ryan Dahlは、これらの課題を解決するために「イベント駆動」と「ノンブロッキングI/O」を核とした新しいアプローチを提案しました。
設計思想
Node.jsの設計は、以下の原則に基づいています。
| 原則 | 説明 |
|---|---|
| シングルスレッド | メインスレッドは1つで、イベントループがすべてを管理 |
| ノンブロッキングI/O | I/O操作を待機せず、コールバックで結果を受け取る |
| イベント駆動 | イベントの発生を監視し、適切なハンドラを実行 |
| モジュラー設計 | 小さなモジュールを組み合わせてアプリケーションを構築 |
V8エンジンとは
V8は、Google Chromeを動かすJavaScriptエンジンです。C++で記述されており、JavaScriptコードを解析して実行します。
V8の特徴
V8エンジンが他のJavaScriptエンジンと異なる点は、JIT(Just-In-Time)コンパイルを採用していることです。
graph LR
A[JavaScript ソースコード] --> B[パース]
B --> C[AST生成]
C --> D[Ignition<br/>インタプリタ]
D --> E[バイトコード]
E --> F{ホットコード?}
F -->|Yes| G[TurboFan<br/>最適化コンパイラ]
G --> H[最適化された<br/>マシンコード]
F -->|No| I[バイトコード実行]V8は、以下の2つのコンパイラを持っています。
- Ignition: ベースラインインタプリタ。JavaScriptをバイトコードに変換して実行
- TurboFan: 最適化コンパイラ。頻繁に実行されるコード(ホットコード)を高度に最適化されたマシンコードにコンパイル
この仕組みにより、JavaScriptは「インタプリタ言語」でありながら、コンパイル言語に匹敵するパフォーマンスを発揮できます。
libuvとは
libuvは、Node.jsの非同期I/Oを実現するためのC言語ライブラリです。イベントループの実装とクロスプラットフォームの非同期I/O操作を提供します。
libuvの役割
graph TD
subgraph "Node.js"
A[JavaScript API]
B[Node.js バインディング]
end
subgraph "libuv"
C[イベントループ]
D[スレッドプール]
E[非同期I/Oハンドル]
end
subgraph "OS"
F[epoll/kqueue/IOCP]
G[ファイルシステム]
H[ネットワーク]
end
A --> B
B --> C
C --> D
C --> E
D --> G
E --> F
F --> Hlibuvは以下の機能を提供します。
| 機能 | 説明 |
|---|---|
| イベントループ | 非同期イベントの監視と処理 |
| スレッドプール | ファイルI/O等のブロッキング操作を別スレッドで実行 |
| 非同期DNS解決 | ホスト名解決を非同期で実行 |
| 非同期ファイルI/O | ファイル操作を非同期で実行 |
| 子プロセス | 外部プロセスの生成と管理 |
| シグナルハンドリング | OSシグナルの処理 |
ブラウザJavaScriptとの違い
ブラウザとNode.jsは、どちらもJavaScriptを実行しますが、利用可能なAPIと実行環境が大きく異なります。
主な違い
| 項目 | ブラウザ | Node.js |
|---|---|---|
| 実行環境 | ブラウザ内 | OS上 |
| DOM操作 | 可能(document, window) |
不可 |
| ファイルシステム | 制限あり(Web APIs経由) | 完全アクセス(fsモジュール) |
| ネットワーク | Fetch API, XMLHttpRequest | http, https, netモジュール |
| モジュールシステム | ES Modules | CommonJS, ES Modules両対応 |
| グローバルオブジェクト | window |
global, globalThis |
| ECMAScriptバージョン | ブラウザ依存 | Node.jsバージョンで決定 |
コード例で見る違い
ブラウザではwindowオブジェクトがグローバルスコープですが、Node.jsではglobalオブジェクトを使用します。
|
|
Node.jsでは、documentやwindowは存在しません。代わりに、processオブジェクトを通じて環境変数やコマンドライン引数にアクセスできます。
|
|
ES2020で導入されたglobalThisを使用すると、環境を問わずグローバルオブジェクトにアクセスできます。
|
|
シングルスレッドとイベントループモデル
Node.jsの最も重要な特徴は、シングルスレッドでありながら高い並行処理能力を持つことです。これはイベントループモデルによって実現されています。
イベントループとは
イベントループは、Node.jsがノンブロッキングI/O操作を実行できる仕組みです。JavaScriptはシングルスレッドで実行されますが、I/O操作はOSカーネルにオフロードされます。
graph TD
A[スクリプト開始] --> B[同期コード実行]
B --> C{イベントキューに<br/>タスクあり?}
C -->|Yes| D[コールバック実行]
D --> C
C -->|No| E{待機中の<br/>タイマー/I/Oあり?}
E -->|Yes| F[待機]
F --> C
E -->|No| G[プロセス終了]イベントループのフェーズ
イベントループは、以下の6つのフェーズで構成されています。
┌───────────────────────────┐
┌─>│ timers │
│ └─────────────┬─────────────┘
│ ┌─────────────┴─────────────┐
│ │ pending callbacks │
│ └─────────────┬─────────────┘
│ ┌─────────────┴─────────────┐
│ │ idle, prepare │
│ └─────────────┬─────────────┘ ┌───────────────┐
│ ┌─────────────┴─────────────┐ │ incoming: │
│ │ poll │<─────┤ connections, │
│ └─────────────┬─────────────┘ │ data, etc. │
│ ┌─────────────┴─────────────┐ └───────────────┘
│ │ check │
│ └─────────────┬─────────────┘
│ ┌─────────────┴─────────────┐
└──┤ close callbacks │
└───────────────────────────┘
各フェーズの役割は以下の通りです。
| フェーズ | 説明 |
|---|---|
| timers | setTimeout()とsetInterval()のコールバックを実行 |
| pending callbacks | 前回のループで延期されたI/Oコールバックを実行 |
| idle, prepare | 内部処理用(通常は使用しない) |
| poll | 新しいI/Oイベントを取得し、I/O関連のコールバックを実行 |
| check | setImmediate()のコールバックを実行 |
| close callbacks | クローズイベントのコールバック(例:socket.on('close'))を実行 |
ノンブロッキングI/Oの仕組み
従来のブロッキングI/Oモデルでは、I/O操作が完了するまでスレッドがブロックされます。
|
|
Node.jsのノンブロッキングI/Oモデルでは、I/O操作を開始した後、即座に制御を返します。
|
|
この非同期モデルにより、Node.jsは単一のスレッドで数千の同時接続を処理できます。
バージョン管理(LTS vs Current)
Node.jsには、2つのリリースラインがあります。適切なバージョンを選択することは、安定した開発環境を維持するために重要です。
リリースサイクル
gantt
title Node.js リリースサイクル
dateFormat YYYY-MM
section v20
Current :2023-04, 6M
Active LTS :2023-10, 12M
Maintenance :2024-10, 18M
section v22
Current :2024-04, 6M
Active LTS :2024-10, 12M
Maintenance :2025-10, 18M
section v24
Current :2025-05, 6M
Active LTS :2025-12, 12MLTS(Long Term Support)とは
LTSは、長期サポート版を意味します。以下の特徴があります。
| 項目 | LTS | Current |
|---|---|---|
| 対象者 | 本番環境での利用者 | 新機能を試したい開発者 |
| サポート期間 | 30ヶ月 | 6ヶ月 |
| 安定性 | 高い | 変更が多い |
| 新機能 | 控えめ | 積極的に追加 |
| バージョン番号 | 偶数(20, 22, 24) | 奇数(21, 23, 25) |
2026年1月時点の最新バージョン
| バージョン | コードネーム | ステータス | 初回リリース |
|---|---|---|---|
| v25 | - | Current | 2025年10月 |
| v24 | Krypton | Active LTS | 2025年5月 |
| v22 | Jod | Maintenance LTS | 2024年4月 |
| v20 | Iron | Maintenance LTS | 2023年4月 |
本番環境では、Active LTSまたはMaintenance LTSバージョンの使用を推奨します。
Node.jsのインストール
公式サイトからのインストール
Node.js公式サイト(https://nodejs.org/)から、お使いのOSに対応したインストーラをダウンロードできます。
Windowsの場合
- https://nodejs.org/ にアクセス
- LTS版のWindowsインストーラ(.msi)をダウンロード
- インストーラを実行し、画面の指示に従う
- インストール完了後、コマンドプロンプトまたはPowerShellで確認
|
|
macOSの場合
- https://nodejs.org/ にアクセス
- LTS版のmacOSインストーラ(.pkg)をダウンロード
- インストーラを実行し、画面の指示に従う
- ターミナルで確認
|
|
Linuxの場合(Ubuntu/Debian)
Node.jsの公式リポジトリを使用してインストールします。
|
|
インストールの確認
インストールが成功したかどうかを確認するには、以下のコマンドを実行します。
|
|
バージョン番号が表示されれば、インストールは成功です。
Node.js REPLの使い方
REPLは、Read-Eval-Print Loopの略で、対話的にJavaScriptコードを実行できる環境です。コードの動作確認やプロトタイピングに便利です。
REPLの起動
ターミナルでnodeコマンドを引数なしで実行すると、REPLが起動します。
|
|
プロンプト(>)が表示されたら、JavaScriptコードを入力できます。
> 1 + 1
2
> 'Hello, ' + 'Node.js'
'Hello, Node.js'
>
基本的な操作
REPLでは、入力したコードが即座に評価され、結果が表示されます。
> const greeting = 'Hello, World!'
undefined
> greeting
'Hello, World!'
> greeting.toUpperCase()
'HELLO, WORLD!'
undefinedは、変数宣言文の戻り値です。式の場合は、その評価結果が表示されます。
複数行のコード入力
関数定義など、複数行にわたるコードも入力できます。REPLは、コードが完結していない場合、自動的に複数行モードに入ります。
> function greet(name) {
... return `Hello, ${name}!`;
... }
undefined
> greet('Node.js')
'Hello, Node.js!'
特殊変数
REPLには、便利な特殊変数があります。
| 変数 | 説明 |
|---|---|
_ |
直前の式の評価結果を保持 |
_error |
直前に発生したエラーを保持 |
> 5 * 10
50
> _ + 10
60
> 'result: ' + _
'result: 60'
ドットコマンド
REPLには、.で始まる特殊コマンドがあります。
| コマンド | 説明 |
|---|---|
.help |
ヘルプを表示 |
.editor |
エディタモードを開始(複数行入力に便利) |
.break |
現在の入力をキャンセル |
.clear |
コンテキストをリセット |
.load |
ファイルからコードを読み込み |
.save |
セッションの履歴をファイルに保存 |
.exit |
REPLを終了 |
> .help
.break Sometimes you get stuck, this gets you out
.clear Alias for .break
.editor Enter editor mode
.exit Exit the REPL
.help Print this help message
.load Load JS from a file into the REPL session
.save Save all evaluated commands in this REPL session to a file
エディタモード
.editorコマンドを使用すると、複数行のコードを快適に入力できます。
> .editor
// エディタモード開始
// コードを入力し、Ctrl+Dで実行
function calculateArea(width, height) {
return width * height;
}
const area = calculateArea(5, 10);
console.log(`面積: ${area}`);
// Ctrl+D を押して実行
面積: 50
undefined
REPLの終了
REPLを終了するには、以下のいずれかの方法を使用します。
.exitコマンドを入力Ctrl+Cを2回押すCtrl+Dを押す
> .exit
最初のNode.jsスクリプト
REPLでの動作確認ができたら、スクリプトファイルを作成して実行してみましょう。
Hello Worldスクリプト
hello.jsという名前のファイルを作成します。
|
|
ターミナルでスクリプトを実行します。
|
|
実行結果は以下のようになります。
Hello, Node.js!
Node.js version: v20.10.0
Platform: win32
Architecture: x64
HTTPサーバーの作成
Node.jsの典型的なユースケースとして、HTTPサーバーを作成してみましょう。
|
|
スクリプトを実行します。
|
|
ブラウザで http://127.0.0.1:3000/ にアクセスすると、「Hello, Node.js!」と表示されます。
サーバーを停止するには、ターミナルでCtrl+Cを押します。
まとめ
本記事では、Node.jsの基礎について解説しました。
- Node.jsとは: V8エンジンを使用したサーバーサイドJavaScriptランタイム
- 歴史と設計思想: 2009年にRyan Dahlが開発。イベント駆動・ノンブロッキングI/Oを採用
- V8エンジン: JITコンパイルにより高速なJavaScript実行を実現
- libuv: クロスプラットフォームの非同期I/Oライブラリ
- ブラウザとの違い: DOM操作不可、ファイルシステムアクセス可能、モジュールシステムの違い
- イベントループ: シングルスレッドで高い並行処理能力を実現する仕組み
- バージョン管理: LTS版(偶数)を本番環境で使用、Current版(奇数)は新機能検証用
- REPL: 対話的なJavaScript実行環境
次のステップとして、nvmやfnmを使用したNode.jsのバージョン管理や、package.jsonを使用したプロジェクト管理について学ぶことをおすすめします。