モジュール: CommonJS モジュール#

安定性: 2 - Stable

CommonJS モジュールは、Node.js 用に JavaScript コードをパッケージ化する本来の方法です。Node.js は、ブラウザーや他の JavaScript ランタイムで使用される ECMAScript モジュール標準もサポートしています。

Node.js では、各ファイルは個別のモジュールとして扱われます。例えば、foo.js という名前のファイルを考えてみましょう。

const circle = require('./circle.js');
console.log(`The area of a circle of radius 4 is ${circle.area(4)}`); 

最初の行で、foo.jsfoo.js と同じディレクトリにあるモジュール circle.js を読み込みます。

circle.js の内容は以下の通りです。

const { PI } = Math;

exports.area = (r) => PI * r ** 2;

exports.circumference = (r) => 2 * PI * r; 

モジュール circle.js は、関数 area()circumference() をエクスポートしています。関数やオブジェクトは、特別な exports オブジェクトに追加のプロパティを指定することで、モジュールのルートに追加されます。

モジュールは Node.js によって関数でラップされているため (モジュールラッパーを参照)、モジュールにローカルな変数はプライベートになります。この例では、変数 PIcircle.js に対してプライベートです。

module.exports プロパティには、新しい値 (関数やオブジェクトなど) を割り当てることができます。

次のコードでは、bar.js は Square クラスをエクスポートする square モジュールを利用しています。

const Square = require('./square.js');
const mySquare = new Square(2);
console.log(`The area of mySquare is ${mySquare.area()}`); 

square モジュールは square.js で定義されています。

// Assigning to exports will not modify module, must use module.exports
module.exports = class Square {
  constructor(width) {
    this.width = width;
  }

  area() {
    return this.width ** 2;
  }
}; 

CommonJS モジュールシステムは、module コアモジュールに実装されています。

有効化#

Node.js には、CommonJS モジュールと ECMAScript モジュールの 2 つのモジュールシステムがあります。

デフォルトでは、Node.js は以下を CommonJS モジュールとして扱います。

  • .cjs 拡張子を持つファイル。

  • 最も近い親の package.json ファイルに、値が "commonjs" のトップレベルフィールド "type" が含まれている場合の .js 拡張子を持つファイル。

  • 最も近い親の package.json ファイルにトップレベルフィールド "type" が含まれていない場合、またはいずれの親フォルダーにも package.json がない場合の、.js 拡張子を持つファイルまたは拡張子のないファイル。ただし、そのファイルが ES モジュールとして評価されない限りエラーとなる構文を含んでいる場合を除きます。パッケージの作者は、すべてのソースが CommonJS であっても "type" フィールドを含めるべきです。パッケージの type を明示的にすることで、ビルドツールやローダーがパッケージ内のファイルをどのように解釈すべきかを判断しやすくなります。

  • 拡張子が .mjs.cjs.json.node.js ではないファイル (最も近い親の package.json ファイルに値が "module" のトップレベルフィールド "type" が含まれている場合、これらのファイルは require() を介してインクルードされた場合にのみ CommonJS モジュールとして認識され、プログラムのコマンドラインエントリポイントとして使用された場合は認識されません)。

詳細については、モジュールシステムの決定を参照してください。

require() の呼び出しは常に CommonJS モジュールローダーを使用します。import() の呼び出しは常に ECMAScript モジュールローダーを使用します。

メインモジュールへのアクセス#

ファイルが Node.js から直接実行されるとき、require.main はその module に設定されます。これは、require.main === module をテストすることで、ファイルが直接実行されたかどうかを判断できることを意味します。

ファイル foo.js の場合、node foo.js で実行された場合は true になりますが、require('./foo') で実行された場合は false になります。

エントリポイントが CommonJS モジュールでない場合、require.mainundefined であり、メインモジュールにはアクセスできません。

パッケージマネージャーのヒント#

Node.js の require() 関数のセマンティクスは、妥当なディレクトリ構造をサポートするのに十分な汎用性を持つように設計されています。dpkgrpmnpm などのパッケージマネージャープログラムは、Node.js モジュールから変更なしでネイティブパッケージをビルドできることを期待しています。

以下に、うまく機能する可能性のある推奨ディレクトリ構造を示します。

/usr/lib/node/<some-package>/<some-version> のフォルダーに、特定のバージョンのパッケージの内容を保持したいとします。

パッケージは互いに依存することができます。パッケージ foo をインストールするには、パッケージ bar の特定のバージョンをインストールする必要があるかもしれません。bar パッケージ自体にも依存関係があり、場合によっては、これらが衝突したり、循環依存を形成したりすることさえあります。

Node.js は、読み込むモジュールの realpath を探し (つまり、シンボリックリンクを解決し)、次に node_modules フォルダーでその依存関係を探すため、この状況は以下のアーキテクチャで解決できます。

  • /usr/lib/node/foo/1.2.3/: foo パッケージ、バージョン 1.2.3 の内容。
  • /usr/lib/node/bar/4.3.2/: foo が依存する bar パッケージの内容。
  • /usr/lib/node/foo/1.2.3/node_modules/bar: /usr/lib/node/bar/4.3.2/ へのシンボリックリンク。
  • /usr/lib/node/bar/4.3.2/node_modules/*: bar が依存するパッケージへのシンボリックリンク。

したがって、循環が発生した場合や依存関係の競合がある場合でも、すべてのモジュールは使用できるバージョンの依存関係を取得できます。

foo パッケージのコードが require('bar') を実行すると、/usr/lib/node/foo/1.2.3/node_modules/bar にシンボリックリンクされているバージョンが取得されます。次に、bar パッケージのコードが require('quux') を呼び出すと、/usr/lib/node/bar/4.3.2/node_modules/quux にシンボリックリンクされているバージョンが取得されます。

さらに、モジュールのルックアッププロセスをさらに最適化するために、パッケージを直接 /usr/lib/node に置くのではなく、/usr/lib/node_modules/<name>/<version> に置くことができます。そうすれば、Node.js は /usr/node_modules/node_modules で見つからない依存関係を探す手間を省けます。

Node.js REPL でモジュールを利用できるようにするには、/usr/lib/node_modules フォルダーを $NODE_PATH 環境変数に追加することも役立つかもしれません。node_modules フォルダーを使用したモジュールのルックアップはすべて相対的であり、require() を呼び出すファイルの実際のパスに基づいているため、パッケージ自体はどこにでも置くことができます。

require() を使用した ECMAScript モジュールの読み込み#

安定性: 1.2 - Release candidate

.mjs 拡張子は ECMAScript モジュール用に予約されています。どのファイルが ECMAScript モジュールとして解析されるかについての詳細は、モジュールシステムの決定セクションを参照してください。

require() は、以下の要件を満たす ECMAScript モジュールの読み込みのみをサポートします。

  • モジュールが完全に同期的であること (トップレベルの await を含まないこと)。かつ、
  • 以下のいずれかの条件が満たされていること。
    1. ファイルが .mjs 拡張子を持っている。
    2. ファイルが .js 拡張子を持ち、最も近い package.json"type": "module" が含まれている。
    3. ファイルが .js 拡張子を持ち、最も近い package.json"type": "commonjs" が含まれておらず、かつモジュールが ES モジュール構文を含んでいる。

読み込まれる ES モジュールが要件を満たす場合、require() はそれを読み込み、モジュール名前空間オブジェクトを返すことができます。この場合、動的な import() と似ていますが、同期的に実行され、名前空間オブジェクトを直接返します。

以下の ES モジュールを使用します。

// distance.mjs
export function distance(a, b) { return Math.sqrt((b.x - a.x) ** 2 + (b.y - a.y) ** 2); } 
// point.mjs
export default class Point {
  constructor(x, y) { this.x = x; this.y = y; }
} 

CommonJS モジュールは require() でこれらを読み込むことができます。

const distance = require('./distance.mjs');
console.log(distance);
// [Module: null prototype] {
//   distance: [Function: distance]
// }

const point = require('./point.mjs');
console.log(point);
// [Module: null prototype] {
//   default: [class Point],
//   __esModule: true,
// } 

ES モジュールを CommonJS に変換し、その後 require() を通じて実際の ES モジュールを読み込む可能性がある既存のツールとの相互運用性のために、返される名前空間は、ツールによって生成された消費コードが実際の ES モジュール内のデフォルトエクスポートを認識できるように、default エクスポートがある場合に __esModule: true プロパティを含みます。名前空間がすでに __esModule を定義している場合、これは追加されません。このプロパティは実験的なものであり、将来変更される可能性があります。これは、既存のエコシステムの慣習に従い、ES モジュールを CommonJS モジュールに変換するツールによってのみ使用されるべきです。CommonJS で直接作成されたコードは、それに依存することを避けるべきです。

ES モジュールが名前付きエクスポートとデフォルトエクスポートの両方を含む場合、require() によって返される結果は、import() によって返される結果と同様に、デフォルトエクスポートを .default プロパティに配置するモジュール名前空間オブジェクトです。require(esm) によって直接返されるべきものをカスタマイズするために、ES モジュールは文字列名 "module.exports" を使用して目的の値をエクスポートできます。

// point.mjs
export default class Point {
  constructor(x, y) { this.x = x; this.y = y; }
}

// `distance` is lost to CommonJS consumers of this module, unless it's
// added to `Point` as a static property.
export function distance(a, b) { return Math.sqrt((b.x - a.x) ** 2 + (b.y - a.y) ** 2); }
export { Point as 'module.exports' } 
const Point = require('./point.mjs');
console.log(Point); // [class Point]

// Named exports are lost when 'module.exports' is used
const { distance } = require('./point.mjs');
console.log(distance); // undefined 

上記の例で、module.exports エクスポート名が使用されると、名前付きエクスポートは CommonJS の利用者には失われることに注意してください。CommonJS の利用者が引き続き名前付きエクスポートにアクセスできるようにするために、モジュールはデフォルトエクスポートが名前付きエクスポートをプロパティとして持つオブジェクトであることを保証できます。例えば上記の例では、distance はデフォルトエクスポートである Point クラスに静的メソッドとしてアタッチできます。

export function distance(a, b) { return Math.sqrt((b.x - a.x) ** 2 + (b.y - a.y) ** 2); }

export default class Point {
  constructor(x, y) { this.x = x; this.y = y; }
  static distance = distance;
}

export { Point as 'module.exports' } 
const Point = require('./point.mjs');
console.log(Point); // [class Point]

const { distance } = require('./point.mjs');
console.log(distance); // [Function: distance] 

require() されるモジュールがトップレベルの await を含む場合、またはそれが import するモジュールグラフがトップレベルの await を含む場合、ERR_REQUIRE_ASYNC_MODULE がスローされます。この場合、ユーザーは import() を使用して非同期モジュールを読み込むべきです。

--experimental-print-required-tla が有効な場合、Node.js は評価前に ERR_REQUIRE_ASYNC_MODULE をスローする代わりに、モジュールを評価し、トップレベルの await を見つけてその場所を出力し、ユーザーが修正するのを助けます。

require() を使用した ES モジュールの読み込みのサポートは現在実験的であり、--no-experimental-require-module を使用して無効にすることができます。この機能がどこで使用されているかを出力するには、--trace-require-module を使用してください。

この機能は、process.features.require_moduletrue であるかを確認することで検出できます。

まとめ#

require() が呼び出されたときに読み込まれる正確なファイル名を取得するには、require.resolve() 関数を使用します。

上記のすべてをまとめると、require() が行うことのハイレベルなアルゴリズムを疑似コードで示します。

require(X) from module at path Y
1. If X is a core module,
   a. return the core module
   b. STOP
2. If X begins with '/'
   a. set Y to the file system root
3. If X is equal to '.', or X begins with './', '/' or '../'
   a. LOAD_AS_FILE(Y + X)
   b. LOAD_AS_DIRECTORY(Y + X)
   c. THROW "not found"
4. If X begins with '#'
   a. LOAD_PACKAGE_IMPORTS(X, dirname(Y))
5. LOAD_PACKAGE_SELF(X, dirname(Y))
6. LOAD_NODE_MODULES(X, dirname(Y))
7. THROW "not found"

MAYBE_DETECT_AND_LOAD(X)
1. If X parses as a CommonJS module, load X as a CommonJS module. STOP.
2. Else, if the source code of X can be parsed as ECMAScript module using
  <a href="esm.md#resolver-algorithm-specification">DETECT_MODULE_SYNTAX defined in
  the ESM resolver</a>,
  a. Load X as an ECMAScript module. STOP.
3. THROW the SyntaxError from attempting to parse X as CommonJS in 1. STOP.

LOAD_AS_FILE(X)
1. If X is a file, load X as its file extension format. STOP
2. If X.js is a file,
    a. Find the closest package scope SCOPE to X.
    b. If no scope was found
      1. MAYBE_DETECT_AND_LOAD(X.js)
    c. If the SCOPE/package.json contains "type" field,
      1. If the "type" field is "module", load X.js as an ECMAScript module. STOP.
      2. If the "type" field is "commonjs", load X.js as a CommonJS module. STOP.
    d. MAYBE_DETECT_AND_LOAD(X.js)
3. If X.json is a file, load X.json to a JavaScript Object. STOP
4. If X.node is a file, load X.node as binary addon. STOP

LOAD_INDEX(X)
1. If X/index.js is a file
    a. Find the closest package scope SCOPE to X.
    b. If no scope was found, load X/index.js as a CommonJS module. STOP.
    c. If the SCOPE/package.json contains "type" field,
      1. If the "type" field is "module", load X/index.js as an ECMAScript module. STOP.
      2. Else, load X/index.js as a CommonJS module. STOP.
2. If X/index.json is a file, parse X/index.json to a JavaScript object. STOP
3. If X/index.node is a file, load X/index.node as binary addon. STOP

LOAD_AS_DIRECTORY(X)
1. If X/package.json is a file,
   a. Parse X/package.json, and look for "main" field.
   b. If "main" is a falsy value, GOTO 2.
   c. let M = X + (json main field)
   d. LOAD_AS_FILE(M)
   e. LOAD_INDEX(M)
   f. LOAD_INDEX(X) DEPRECATED
   g. THROW "not found"
2. LOAD_INDEX(X)

LOAD_NODE_MODULES(X, START)
1. let DIRS = NODE_MODULES_PATHS(START)
2. for each DIR in DIRS:
   a. LOAD_PACKAGE_EXPORTS(X, DIR)
   b. LOAD_AS_FILE(DIR/X)
   c. LOAD_AS_DIRECTORY(DIR/X)

NODE_MODULES_PATHS(START)
1. let PARTS = path split(START)
2. let I = count of PARTS - 1
3. let DIRS = []
4. while I >= 0,
   a. if PARTS[I] = "node_modules", GOTO d.
   b. DIR = path join(PARTS[0 .. I] + "node_modules")
   c. DIRS = DIR + DIRS
   d. let I = I - 1
5. return DIRS + GLOBAL_FOLDERS

LOAD_PACKAGE_IMPORTS(X, DIR)
1. Find the closest package scope SCOPE to DIR.
2. If no scope was found, return.
3. If the SCOPE/package.json "imports" is null or undefined, return.
4. If `--experimental-require-module` is enabled
  a. let CONDITIONS = ["node", "require", "module-sync"]
  b. Else, let CONDITIONS = ["node", "require"]
5. let MATCH = PACKAGE_IMPORTS_RESOLVE(X, pathToFileURL(SCOPE),
  CONDITIONS) <a href="esm.md#resolver-algorithm-specification">defined in the ESM resolver</a>.
6. RESOLVE_ESM_MATCH(MATCH).

LOAD_PACKAGE_EXPORTS(X, DIR)
1. Try to interpret X as a combination of NAME and SUBPATH where the name
   may have a @scope/ prefix and the subpath begins with a slash (`/`).
2. If X does not match this pattern or DIR/NAME/package.json is not a file,
   return.
3. Parse DIR/NAME/package.json, and look for "exports" field.
4. If "exports" is null or undefined, return.
5. If `--experimental-require-module` is enabled
  a. let CONDITIONS = ["node", "require", "module-sync"]
  b. Else, let CONDITIONS = ["node", "require"]
6. let MATCH = PACKAGE_EXPORTS_RESOLVE(pathToFileURL(DIR/NAME), "." + SUBPATH,
   `package.json` "exports", CONDITIONS) <a href="esm.md#resolver-algorithm-specification">defined in the ESM resolver</a>.
7. RESOLVE_ESM_MATCH(MATCH)

LOAD_PACKAGE_SELF(X, DIR)
1. Find the closest package scope SCOPE to DIR.
2. If no scope was found, return.
3. If the SCOPE/package.json "exports" is null or undefined, return.
4. If the SCOPE/package.json "name" is not the first segment of X, return.
5. let MATCH = PACKAGE_EXPORTS_RESOLVE(pathToFileURL(SCOPE),
   "." + X.slice("name".length), `package.json` "exports", ["node", "require"])
   <a href="esm.md#resolver-algorithm-specification">defined in the ESM resolver</a>.
6. RESOLVE_ESM_MATCH(MATCH)

RESOLVE_ESM_MATCH(MATCH)
1. let RESOLVED_PATH = fileURLToPath(MATCH)
2. If the file at RESOLVED_PATH exists, load RESOLVED_PATH as its extension
   format. STOP
3. THROW "not found" 

キャッシュ#

モジュールは初めて読み込まれた後にキャッシュされます。これは (とりわけ) require('foo') を呼び出すたびに、同じファイルに解決されるのであれば、まったく同じオブジェクトが返されることを意味します。

require.cache が変更されない限り、require('foo') を複数回呼び出しても、モジュールコードが複数回実行されることはありません。これは重要な機能です。これにより、「部分的に完了した」オブジェクトを返すことができ、循環を引き起こす場合でも推移的な依存関係を読み込むことができます。

モジュールにコードを複数回実行させたい場合は、関数をエクスポートし、その関数を呼び出してください。

モジュールキャッシュの注意点#

モジュールは、解決されたファイル名に基づいてキャッシュされます。モジュールは呼び出し元のモジュールの場所 (node_modules フォルダーからの読み込み) に基づいて異なるファイル名に解決される可能性があるため、require('foo') が常にまったく同じオブジェクトを返すことは保証されません。

さらに、大文字と小文字を区別しないファイルシステムやオペレーティングシステムでは、異なる解決済みファイル名が同じファイルを指すことがありますが、キャッシュはそれらを異なるモジュールとして扱い、ファイルを複数回リロードします。例えば、require('./foo')require('./FOO') は、./foo./FOO が同じファイルであるかどうかに関わらず、2つの異なるオブジェクトを返します。

組み込みモジュール#

Node.js には、バイナリにコンパイルされたいくつかのモジュールがあります。これらのモジュールについては、このドキュメントの他の場所で詳しく説明されています。

組み込みモジュールは Node.js のソース内で定義され、lib/ フォルダーにあります。

組み込みモジュールは node: プレフィックスを使用して識別でき、その場合は require キャッシュをバイパスします。例えば、require('node:http') は、その名前の require.cache エントリが存在する場合でも、常に組み込みの HTTP モジュールを返します。

一部の組み込みモジュールは、その識別子が require() に渡された場合に常に優先的に読み込まれます。例えば、require('http') は、その名前のファイルが存在する場合でも、常に組み込みの HTTP モジュールを返します。

すべての組み込みモジュールのリストは module.builtinModules から取得できます。モジュールは、次のセクションで説明するように、そのようなプレフィックスを必須とするものを除き、すべて node: プレフィックスなしでリストされています。

node: プレフィックスが必須の組み込みモジュール#

require() によって読み込まれる際、一部の組み込みモジュールは node: プレフィックス付きでリクエストする必要があります。この要件は、新しく導入された組み込みモジュールが、すでにその名前を使用しているユーザーランドパッケージと競合するのを防ぐために存在します。現在 node: プレフィックスを必要とする組み込みモジュールは以下の通りです。

これらのモジュールのリストは、プレフィックスを含めて module.builtinModules で公開されています。

循環#

循環的な require() 呼び出しがある場合、モジュールは返されるときに実行が完了していない可能性があります。

この状況を考えてみましょう。

a.js:

console.log('a starting');
exports.done = false;
const b = require('./b.js');
console.log('in a, b.done = %j', b.done);
exports.done = true;
console.log('a done'); 

b.js:

console.log('b starting');
exports.done = false;
const a = require('./a.js');
console.log('in b, a.done = %j', a.done);
exports.done = true;
console.log('b done'); 

main.js:

console.log('main starting');
const a = require('./a.js');
const b = require('./b.js');
console.log('in main, a.done = %j, b.done = %j', a.done, b.done); 

main.jsa.js を読み込むと、a.js は次に b.js を読み込みます。その時点で、b.jsa.js を読み込もうとします。無限ループを防ぐために、a.js の exports オブジェクトの 未完成のコピーb.js モジュールに返されます。その後、b.js の読み込みが完了し、その exports オブジェクトが a.js モジュールに提供されます。

main.js が両方のモジュールを読み込む頃には、両方とも完了しています。したがって、このプログラムの出力は次のようになります。

$ node main.js
main starting
a starting
b starting
in b, a.done = false
b done
in a, b.done = true
a done
in main, a.done = true, b.done = true 

循環的なモジュールの依存関係がアプリケーション内で正しく機能するようにするには、慎重な計画が必要です。

ファイルモジュール#

正確なファイル名が見つからない場合、Node.js は .js.json、そして最後に .node の拡張子を追加して、必要なファイル名を読み込もうとします。異なる拡張子 (例: .cjs) を持つファイルを読み込む場合は、そのファイル拡張子を含む完全な名前を require() に渡す必要があります (例: require('./file.cjs'))。

.json ファイルは JSON テキストファイルとして解析され、.node ファイルは process.dlopen() で読み込まれるコンパイル済みアドオンモジュールとして解釈されます。他の拡張子 (または拡張子なし) を使用するファイルは、JavaScript テキストファイルとして解析されます。どの解析ゴールが使用されるかを理解するには、モジュールシステムの決定セクションを参照してください。

'/' で始まる必須モジュールは、ファイルへの絶対パスです。例えば、require('/home/marco/foo.js')/home/marco/foo.js のファイルを読み込みます。

'./' で始まる必須モジュールは、require() を呼び出しているファイルからの相対パスです。つまり、require('./circle')circle.js を見つけるには、circle.jsfoo.js と同じディレクトリにある必要があります。

先頭に '/''./'、または '../' がない場合、モジュールはコアモジュールであるか、node_modules フォルダーから読み込まれる必要があります。

指定されたパスが存在しない場合、require()MODULE_NOT_FOUND エラーをスローします。

モジュールとしてのフォルダー#

安定性: 3 - レガシー: 代わりに サブパスエクスポートまたはサブパスインポートを使用してください。

フォルダーを引数として require() に渡すには、3 つの方法があります。

1つ目は、フォルダーのルートに main モジュールを指定する package.json ファイルを作成することです。package.json ファイルの例は次のようになります。

{ "name" : "some-library",
  "main" : "./lib/some-library.js" } 

これが ./some-library のフォルダーにある場合、require('./some-library')./some-library/lib/some-library.js を読み込もうとします。

ディレクトリに package.json ファイルが存在しない場合、または "main" エントリが欠落しているか解決できない場合、Node.js はそのディレクトリから index.js または index.node ファイルを読み込もうとします。例えば、前の例で package.json ファイルがなかった場合、require('./some-library') は以下を読み込もうとします。

  • ./some-library/index.js
  • ./some-library/index.node

これらの試みが失敗した場合、Node.js はデフォルトのエラーでモジュール全体が見つからないと報告します。

Error: Cannot find module 'some-library' 

上記の3つのケースすべてで、import('./some-library') の呼び出しは ERR_UNSUPPORTED_DIR_IMPORT エラーになります。パッケージの サブパスエクスポート または サブパスインポート を使用すると、モジュールとしてのフォルダーと同じ封じ込め組織の利点が得られ、requireimport の両方で機能します。

node_modules フォルダーからの読み込み#

require() に渡されたモジュール識別子が組み込みモジュールではなく、'/''../'、または './'で始まらない場合、Node.js は現在のモジュールのディレクトリから開始し、/node_modules を追加して、その場所からモジュールを読み込もうとします。Node.js は、既に node_modules で終わるパスに node_modules を追加しません。

そこで見つからない場合、親ディレクトリに移動し、ファイルシステムのルートに到達するまでこれを繰り返します。

例えば、'/home/ry/projects/foo.js' のファイルが require('bar.js') を呼び出した場合、Node.js は次の場所をこの順序で探します。

  • /home/ry/projects/node_modules/bar.js
  • /home/ry/node_modules/bar.js
  • /home/node_modules/bar.js
  • /node_modules/bar.js

これにより、プログラムは依存関係をローカライズして、衝突しないようにすることができます。

モジュール名にパスの接尾辞を含めることで、モジュールと共に配布される特定のファイルやサブモジュールを require することが可能です。例えば、require('example-module/path/to/file')example-module がある場所を基準に path/to/file を解決します。接尾辞付きのパスは、同じモジュール解決セマンティクスに従います。

グローバルフォルダーからの読み込み#

NODE_PATH 環境変数がコロン区切りの絶対パスのリストに設定されている場合、Node.js は他の場所で見つからなかった場合にそれらのパスでモジュールを検索します。

Windowsでは、NODE_PATHはコロン (:) の代わりにセミコロン (;) で区切られます。

NODE_PATH は、現在のモジュール解決アルゴリズムが定義される前に、さまざまなパスからモジュールを読み込むことをサポートするために元々作成されました。

NODE_PATH はまだサポートされていますが、Node.js エコシステムが依存モジュールの場所を特定するための慣習に落ち着いた今、その必要性は低くなっています。NODE_PATH に依存するデプロイメントは、NODE_PATH を設定する必要があることを人々が知らない場合に、驚くべき動作を示すことがあります。モジュールの依存関係が変更され、NODE_PATH が検索されるにつれて異なるバージョン (あるいは異なるモジュール) が読み込まれることもあります。

さらに、Node.js は次の GLOBAL_FOLDERS のリストを検索します。

  • 1: $HOME/.node_modules
  • 2: $HOME/.node_libraries
  • 3: $PREFIX/lib/node

ここで $HOME はユーザーのホームディレクトリ、$PREFIX は Node.js で設定された node_prefix です。

これらは主に歴史的な理由によるものです。

ローカルの node_modules フォルダーに依存関係を配置することが強く推奨されます。これらはより速く、より確実に読み込まれます。

モジュールラッパー#

モジュールのコードが実行される前に、Node.js はそれを次のような関数ラッパーでラップします。

(function(exports, require, module, __filename, __dirname) {
// Module code actually lives in here
}); 

これを行うことにより、Node.js はいくつかのことを達成します。

  • トップレベルの変数 (var, const, or let で定義) をグローバルオブジェクトではなく、モジュールにスコープを限定します。
  • 実際にはモジュールに固有の、グローバルに見えるいくつかの変数を提供するのに役立ちます。例えば:
    • 実装者がモジュールから値をエクスポートするために使用できる module および exports オブジェクト。
    • モジュールの絶対ファイル名とディレクトリパスを含む便利な変数 __filename および __dirname

モジュールスコープ#

__dirname#

現在のモジュールのディレクトリ名。これは __filenamepath.dirname() と同じです。

例: /Users/mjr から node example.js を実行

console.log(__dirname);
// Prints: /Users/mjr
console.log(path.dirname(__filename));
// Prints: /Users/mjr 

__filename#

現在のモジュールのファイル名。これは、シンボリックリンクが解決された現在のモジュールファイルの絶対パスです。

メインプログラムの場合、これはコマンドラインで使用されたファイル名と必ずしも同じではありません。

現在のモジュールのディレクトリ名については __dirname を参照してください。

/Users/mjr から node example.js を実行

console.log(__filename);
// Prints: /Users/mjr/example.js
console.log(__dirname);
// Prints: /Users/mjr 

ab の 2 つのモジュールがあり、ba の依存関係で、ディレクトリ構造は次のようになっているとします。

  • /Users/mjr/app/a.js
  • /Users/mjr/app/node_modules/b/b.js

b.js 内の __filename への参照は /Users/mjr/app/node_modules/b/b.js を返し、a.js 内の __filename への参照は /Users/mjr/app/a.js を返します。

exports#

module.exports への参照で、より短くタイプできます。exports ショートカットに関するセクションで、いつ exports を使い、いつ module.exports を使うかの詳細を参照してください。

module#

現在のモジュールへの参照です。module オブジェクトに関するセクションを参照してください。特に、module.exports は、モジュールが何をエクスポートし、require() を通じて利用可能にするかを定義するために使用されます。

require(id)#

  • id <string> モジュール名またはパス
  • 戻り値: <any> エクスポートされたモジュールの内容

モジュール、JSON、およびローカルファイルをインポートするために使用されます。モジュールは node_modules からインポートできます。ローカルモジュールと JSON ファイルは、__dirname (定義されている場合) または現在の作業ディレクトリに対して解決される相対パス (例: ./, ./foo, ./bar/baz, ../foo) を使用してインポートできます。POSIX スタイルの相対パスは OS に依存しない方法で解決されるため、上記の例は Unix システムと同様に Windows でも機能します。

// Importing a local module with a path relative to the `__dirname` or current
// working directory. (On Windows, this would resolve to .\path\myLocalModule.)
const myLocalModule = require('./path/myLocalModule');

// Importing a JSON file:
const jsonData = require('./path/filename.json');

// Importing a module from node_modules or Node.js built-in module:
const crypto = require('node:crypto'); 
require.cache#

モジュールは、require されたときにこのオブジェクトにキャッシュされます。このオブジェクトからキーと値を削除すると、次の require でモジュールがリロードされます。これはネイティブアドオンには適用されず、リロードするとエラーが発生します。

エントリの追加や置換も可能です。このキャッシュは組み込みモジュールの前にチェックされ、組み込みモジュールと一致する名前がキャッシュに追加された場合、node: プレフィックス付きの require 呼び出しのみが組み込みモジュールを受け取ります。注意して使用してください!

const assert = require('node:assert');
const realFs = require('node:fs');

const fakeFs = {};
require.cache.fs = { exports: fakeFs };

assert.strictEqual(require('fs'), fakeFs);
assert.strictEqual(require('node:fs'), realFs); 
require.extensions#

安定性: 0 - 非推奨

require に、特定のファイル拡張子の処理方法を指示します。

拡張子 .sjs のファイルを .js として処理します。

require.extensions['.sjs'] = require.extensions['.js']; 

非推奨です。 過去には、このリストは非 JavaScript モジュールをオンデマンドでコンパイルして Node.js にロードするために使用されていました。しかし、実際には、他の Node.js プログラムを介してモジュールをロードしたり、事前に JavaScript にコンパイルしたりするなど、はるかに良い方法があります。

require.extensions の使用は避けてください。使用すると微妙なバグを引き起こす可能性があり、登録された拡張子ごとに拡張子の解決が遅くなります。

require.main#

Node.js プロセスが起動したときにロードされたエントリスクリプトを表す Module オブジェクト、またはプログラムのエントリポイントが CommonJS モジュールでない場合は undefined です。「メインモジュールへのアクセス」を参照してください。

entry.js スクリプト内

console.log(require.main); 
node entry.js 
Module {
  id: '.',
  path: '/absolute/path/to',
  exports: {},
  filename: '/absolute/path/to/entry.js',
  loaded: false,
  children: [],
  paths:
   [ '/absolute/path/to/node_modules',
     '/absolute/path/node_modules',
     '/absolute/node_modules',
     '/node_modules' ] } 
require.resolve(request[, options])#
  • request <string> 解決するモジュールパス。
  • options <Object>
    • paths <string[]> モジュールの場所を解決するためのパス。存在する場合、これらのパスはデフォルトの解決パスの代わりに使用されますが、常に含まれる GLOBAL_FOLDERS ($HOME/.node_modules など) は例外です。これらの各パスはモジュール解決アルゴリズムの開始点として使用され、つまり node_modules 階層はこの場所からチェックされます。
  • 戻り値: <string>

内部の require() 機構を使用してモジュールの場所を検索しますが、モジュールをロードするのではなく、解決されたファイル名だけを返します。

モジュールが見つからない場合、MODULE_NOT_FOUND エラーがスローされます。

require.resolve.paths(request)#

request の解決中に検索されたパスを含む配列を返します。request 文字列がコアモジュール (例: httpfs) を参照する場合は null を返します。

module オブジェクト#

各モジュールにおいて、フリー変数 module は現在のモジュールを表すオブジェクトへの参照です。便宜上、module.exports はモジュールグローバルの exports を介してもアクセスできます。module は実際にはグローバルではなく、各モジュールに対してローカルです。

module.children#

このモジュールによって初めて require されたモジュールオブジェクト。

module.exports#

module.exports オブジェクトは Module システムによって作成されます。これが受け入れられない場合もあります。多くの人は、自分のモジュールがあるクラスのインスタンスであることを望みます。これを行うには、目的のエクスポートオブジェクトを module.exports に割り当てます。目的のオブジェクトを exports に割り当てると、ローカルの exports 変数が再バインドされるだけで、おそらくそれは望ましくありません。

例えば、a.js というモジュールを作成していたとします。

const EventEmitter = require('node:events');

module.exports = new EventEmitter();

// Do some work, and after some time emit
// the 'ready' event from the module itself.
setTimeout(() => {
  module.exports.emit('ready');
}, 1000); 

そして、別のファイルで次のようにできます。

const a = require('./a');
a.on('ready', () => {
  console.log('module "a" is ready');
}); 

module.exports への割り当ては、すぐに行う必要があります。どのコールバック内でも行うことはできません。これは機能しません。

x.js:

setTimeout(() => {
  module.exports = { a: 'hello' };
}, 0); 

y.js:

const x = require('./x');
console.log(x.a); 
exports ショートカット#

exports 変数は、モジュールのファイルレベルのスコープ内で利用可能で、モジュールが評価される前に module.exports の値が割り当てられます。

これにより、module.exports.f = ...exports.f = ... のように簡潔に書くことができるショートカットが可能になります。ただし、他の変数と同様に、新しい値が exports に割り当てられると、それはもはや module.exports にバインドされなくなることに注意してください。

module.exports.hello = true; // Exported from require of module
exports = { hello: false };  // Not exported, only available in the module 

module.exports プロパティが新しいオブジェクトで完全に置き換えられる場合、exports も再割り当てするのが一般的です。

module.exports = exports = function Constructor() {
  // ... etc.
}; 

この動作を説明するために、require() のこの仮説的な実装を想像してみてください。これは実際に require() によって行われることと非常に似ています。

function require(/* ... */) {
  const module = { exports: {} };
  ((module, exports) => {
    // Module code here. In this example, define a function.
    function someFunc() {}
    exports = someFunc;
    // At this point, exports is no longer a shortcut to module.exports, and
    // this module will still export an empty default object.
    module.exports = someFunc;
    // At this point, the module will now export someFunc, instead of the
    // default object.
  })(module, module.exports);
  return module.exports;
} 

module.filename#

モジュールの完全に解決されたファイル名。

module.id#

モジュールの識別子。通常、これは完全に解決されたファイル名です。

module.isPreloading#

  • 型: <boolean> モジュールが Node.js のプリロードフェーズ中に実行されている場合は true

module.loaded#

モジュールの読み込みが完了したか、または読み込み中であるかどうか。

module.parent#

安定性: 0 - 非推奨: 代わりに require.mainmodule.children を使用してください。

このモジュールを最初に require したモジュール。現在のモジュールが現在のプロセスのエントリポイントである場合は null、またはモジュールが CommonJS モジュールではない何か (例: REPL や import) によってロードされた場合は undefined

module.path#

モジュールのディレクトリ名。これは通常、module.idpath.dirname() と同じです。

module.paths#

モジュールの検索パス。

module.require(id)#

  • id <string>
  • 戻り値: <any> エクスポートされたモジュールの内容

module.require() メソッドは、元のモジュールから require() が呼び出されたかのようにモジュールをロードする方法を提供します。

これを行うためには、module オブジェクトへの参照を取得する必要があります。require()module.exports を返し、module は通常、特定のモジュールのコード内でのみ利用可能であるため、使用するためには明示的にエクスポートする必要があります。

Module オブジェクト#

このセクションはモジュール: module コアモジュールに移動しました。

ソースマップ v3 サポート#

このセクションはモジュール: module コアモジュールに移動しました。