<CodeLearn/>
Node.js レッスン1

Node.jsの基本

サーバーサイドJavaScriptの世界へようこそ

Node.jsとは何か?

Node.jsは、GoogleのV8 JavaScriptエンジンをベースにした、サーバーサイドのJavaScript実行環境です。 2009年にRyan Dahlによって開発されました。ブラウザでしか動かなかったJavaScriptを、 サーバーやコマンドラインでも実行できるようにした革命的なプラットフォームです。

Node.jsの特徴は、非同期・ノンブロッキングI/Oモデルです。 従来のサーバー(Apache等)はリクエストごとにスレッドを生成しますが、 Node.jsはシングルスレッドでイベントループを使い、大量の同時接続を効率的に処理します。

// Node.jsのバージョン確認
// ターミナルで実行:
// $ node --version
// v20.11.0

// Node.jsの対話モード(REPL)を起動:
// $ node
// > 1 + 2
// 3
// > 'Hello' + ' World'
// 'Hello World'
// > .exit

V8エンジンとイベントループ

V8エンジンは、Google Chromeで使われている 高速なJavaScriptエンジンです。JavaScriptコードを直接マシンコードにコンパイル(JIT)するため、 非常に高いパフォーマンスを発揮します。

イベントループは、Node.jsの心臓部です。 シングルスレッドでありながら、非同期I/O操作をキューで管理し、 完了した処理のコールバックを順次実行していきます。

// イベントループの動作を理解する例
console.log('1: 同期処理 - 最初に実行');

setTimeout(() => {
  console.log('2: タイマー - イベントループで後から実行');
}, 0);

Promise.resolve().then(() => {
  console.log('3: マイクロタスク - タイマーより先に実行');
});

console.log('4: 同期処理 - 2番目に実行');

// 出力順序:
// 1: 同期処理 - 最初に実行
// 4: 同期処理 - 2番目に実行
// 3: マイクロタスク - タイマーより先に実行
// 2: タイマー - イベントループで後から実行

ノンブロッキングI/O

Node.jsの最大の特徴は、I/O操作(ファイル読み書き、ネットワーク通信、データベースアクセス)がノンブロッキングであることです。 処理の完了を待たずに次の処理に進み、完了時にコールバックで結果を受け取ります。

const fs = require('fs');

// ブロッキング(同期)- 読み込みが完了するまで次に進めない
const data = fs.readFileSync('file.txt', 'utf8');
console.log(data);
console.log('同期: ファイル読み込み後に実行');

// ノンブロッキング(非同期)- 読み込み中も次の処理に進める
fs.readFile('file.txt', 'utf8', (err, data) => {
  if (err) {
    console.error('エラー:', err.message);
    return;
  }
  console.log(data);
});
console.log('非同期: ファイル読み込み前に実行される!');

// async/await を使ったモダンな書き方
const fsPromises = require('fs').promises;

async function readFile() {
  try {
    const data = await fsPromises.readFile('file.txt', 'utf8');
    console.log(data);
  } catch (err) {
    console.error('エラー:', err.message);
  }
}

スクリプトの実行とREPL

Node.jsでJavaScriptを実行するには、主に2つの方法があります。スクリプトファイルの実行と、REPL(対話モード)です。

// === スクリプトファイルの実行 ===
// app.js を作成して実行する

// app.js
function greet(name) {
  return `こんにちは、${name}さん!`;
}

const message = greet('太郎');
console.log(message);  // こんにちは、太郎さん!

// ターミナルで実行:
// $ node app.js
// こんにちは、太郎さん!

// === REPL(Read-Eval-Print Loop) ===
// ターミナルで 'node' と入力すると対話モードに入る
// $ node
// > const x = 10;
// undefined
// > x * 2
// 20
// > [1, 2, 3].map(n => n ** 2)
// [ 1, 4, 9 ]
// > .help     // コマンド一覧
// > .exit     // 終了

グローバルオブジェクト

Node.jsには、ブラウザのwindowの代わりに、 サーバーサイド固有のグローバルオブジェクトが用意されています。

// __dirname: 現在のファイルがあるディレクトリの絶対パス
console.log(__dirname);
// 例: /Users/user/projects/my-app

// __filename: 現在のファイルの絶対パス
console.log(__filename);
// 例: /Users/user/projects/my-app/app.js

// process: Node.jsプロセスの情報と制御
console.log(process.version);    // v20.11.0
console.log(process.platform);   // darwin, linux, win32
console.log(process.cwd());      // カレントディレクトリ
console.log(process.env.HOME);   // 環境変数にアクセス
console.log(process.argv);       // コマンドライン引数

// process.exit() でプロセスを終了
// process.exit(0);  // 正常終了
// process.exit(1);  // エラー終了

// global: グローバルオブジェクト(ブラウザのwindowに相当)
console.log(global === globalThis); // true

// console: おなじみのコンソール出力
console.log('通常のログ');
console.error('エラーログ');
console.warn('警告ログ');
console.time('timer');
// ...処理...
console.timeEnd('timer'); // timer: 〇〇ms

// Buffer: バイナリデータを扱う
const buf = Buffer.from('こんにちは', 'utf8');
console.log(buf);           // <Buffer e3 81 93 ...>
console.log(buf.toString()); // こんにちは

確認クイズ

1 / 3

Node.jsが使用しているJavaScriptエンジンはどれ?

まとめ

  • Node.jsはV8エンジン上で動くサーバーサイドJavaScript実行環境
  • イベントループとノンブロッキングI/Oにより、高い並行処理性能を持つ
  • 同期処理と非同期処理の違いを理解することが重要
  • process__dirnameBufferなどNode.js固有のグローバルオブジェクトがある
  • REPLで気軽に試し、スクリプトファイルで本格的なアプリを構築する