はじめに
「Node.js は実行環境」という説明は聞いたことがありましたが、あまりピンときていませんでした。
普段は Java を使うことが多いので、Java と比較しながら調べた内容をまとめます。
Node.js は JavaScript の実行環境
Node.js は、JavaScript のための JRE に相当します。
JavaScript はもともとブラウザの中でだけ動く言語でした。
2009 年に Chrome の JavaScript エンジン(V8)をブラウザから切り出し、ファイル操作やネットワークの機能を足して、サーバやコマンドラインでも動かせるようにしたものが Node.js です。
同じ言語に「ブラウザ」と「Node.js」という 2 つの実行環境がある点が、Java と大きく違います。
| Java | Node.js | 役割 |
|---|---|---|
| JRE / JVM | Node.js | 実行環境 |
| javac | tsc(TypeScript → JavaScript) | コンパイラ |
java.base などの標準ライブラリ |
node:http、node:fs などの組み込みモジュール |
実行環境が最初から持つ機能 |
| Maven / Gradle | npm | 外部ライブラリの管理 |
~/.m2/repository |
node_modules |
外部ライブラリの置き場 |
| SDKMAN / jEnv | nvm | 実行環境のバージョン切り替え |
~/.m2とは、Maven を一度でも実行するとホームディレクトリに作られる隠しフォルダで、中身は 2 つです。
・settings.xml: Maven 全体の設定(プロキシ、ミラー、リポジトリの認証情報など)
・repository/: ダウンロードした jar の保管庫。ローカルリポジトリとも呼ばれます
~/.m2の「m2」は Maven 2 の略です。2005 年の Maven 2 で仕組みが作り直されたときに決まった名前で、Maven 3 以降も互換のためそのまま使われています。Gradle では~/.gradle/cachesが同じ役割です。
npm 側で対応するのは次の 2 つです。
| Maven | npm | 役割 |
|---|---|---|
~/.m2/settings.xml |
~/.npmrc |
ツール全体の設定 |
~/.m2/repository |
~/.npm/_cacache |
ダウンロード済みパッケージのキャッシュ |
※ただし npm はキャッシュから直接は使わず、各プロジェクトの node_modules にコピーして展開します。Maven が ~/.m2 の jar をそのままクラスパスに載せるのとは、ここが違います。
組み込みモジュールはどこにあるか
http、fs、path などの組み込みモジュールは、node という実行ファイル 1 つの中に埋め込まれています。
フォルダに点在しているわけではなく、別途ダウンロードするものでもありません。
たとえば nvm で入れた Node 22 なら、次の 1 ファイルに全組み込みモジュールが入っています。
~/.nvm/versions/node/v22.19.0/bin/node
JRE が lib/modules という 1 ファイルに java.base を収めているのと同じ構造です。
node_modules は標準ライブラリではない
名前に module が入っていますが、node_modules は 外部ライブラリをダウンロードして置くフォルダです。
Java でいえば Maven の ~/.m2/repository に相当します(express や @apollo/server はここに入ります)。
Java との違いは置き場所のスコープです。
- Maven:
~/.m2/repositoryに、マシン全体で 1 か所 - npm: プロジェクトごとに
node_modulesを作る。そのため.gitignoreに入れておき、クローンした人は各自npm installで作り直す
import 文での見分け方
import http from 'node:http'; // 組み込み。node 本体の中
import express from 'express'; // 外部。node_modules/express
import { ApolloServer } from '@apollo/server'; // 外部。node_modules/@apollo/server
import { resolvers } from './resolvers'; // 自分のコード。相対パス
-
node:で始まる → 組み込み(java.base相当) - 名前だけ →
node_modulesから探す -
./や../で始まる → プロジェクト内のファイル
node:http と http の違い
どちらも動きますが、node: 接頭辞を付けるのが現在の推奨です。
- npm パッケージと組み込みを一目で区別できる
- 同名の npm パッケージとの取り違えを防げる
-
node:testなど新しい組み込みモジュールはnode:でしか読み込めない
ルールとしては「Node 組み込みには node: を付け、npm から入れたものには付けない」で統一できます。
補足
組み込みモジュールの型定義は @types/node という外部パッケージにあります。
これは TypeScript が補完や型チェックに使うだけで、実体はあくまで node 本体の中です。
おわりに
今までよく分からずに使っていましたが、普段使っている言語と対応させて考えると理解しやすくなりました。
