Skip to content

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

[Stable: 2 - 安定]

Stable: 2 安定度: 2 - 安定

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

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

js
const circle = require('./circle.js')
console.log(`半径 4 の円の面積は ${circle.area(4)} です`)

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

circle.js の内容は次のとおりです。

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.jsSquare クラスをエクスポートする square モジュールを使用しています。

js
const Square = require('./square.js')
const mySquare = new Square(2)
console.log(`mySquare の面積は ${mySquare.area()} です`)

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

js
// exports に代入しても module は変更されないため、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 モジュールの読み込み

[履歴]

バージョン変更点
v23.5.0この機能はデフォルトで実験的な警告を出力しなくなりましたが、--trace-require-module を使用すると警告を出力できます。
v23.0.0この機能は、--experimental-require-module CLI フラグの対象外になりました。
v23.0.0require(esm)'module.exports' インターオペラビリティエクスポートをサポート
v22.0.0, v20.17.0追加: v22.0.0, v20.17.0

[安定版: 1 - 実験的]

安定版: 1 安定性: 1.2 - リリース候補

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

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

  • モジュールは完全に同期している(最上位レベルの await を含んでいない)。
  • 次のいずれかの条件を満たしている。

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

次の ES モジュールの場合:

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

CommonJS モジュールは require() を使用してそれらをロードできます。

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

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

js
// 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 (b.x - a.x) ** 2 + (b.y - a.y) ** 2
}
export { Point as 'module.exports' }
js
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 クラスに静的メソッドとして添付できます。

js
export function distance(a, b) {
  return (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' }
js
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 が有効になっている場合、評価前に ERR_REQUIRE_ASYNC_MODULE をスローする代わりに、Node.js はモジュールを評価し、最上位レベルの await を特定しようと試み、その場所を出力してユーザーが修正するのに役立ちます。

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

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

すべてまとめて

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

上記のすべてをまとめると、require() が行う処理の高レベルアルゴリズムは擬似コードで次のようになります。

text
path Y のモジュールから require(X)
1. X がコアモジュールの場合、
   a. コアモジュールを返す
   b. 終了
2. X が '/' で始まる場合、
   a. Y をファイルシステムルートに設定する
3. X が './' または '/' または '../' で始まる場合、
   a. LOAD_AS_FILE(Y + X)
   b. LOAD_AS_DIRECTORY(Y + X)
   c. "not found" をスロー
4. X が '#' で始まる場合、
   a. LOAD_PACKAGE_IMPORTS(X, dirname(Y))
5. LOAD_PACKAGE_SELF(X, dirname(Y))
6. LOAD_NODE_MODULES(X, dirname(Y))
7. "not found" をスロー

MAYBE_DETECT_AND_LOAD(X)
1. X が CommonJS モジュールとして解析できる場合、X を CommonJS モジュールとしてロードする。終了。
2. そうでない場合、X のソースコードが
  <a href="esm#resolver-algorithm-specification">ESM レゾルバで定義されている DETECT_MODULE_SYNTAX</a> を使用して ECMAScript モジュールとして解析できる場合、
  a. X を ECMAScript モジュールとしてロードする。終了。
3. 1. で X を CommonJS として解析しようとしたときの SyntaxError をスローする。終了。

LOAD_AS_FILE(X)
1. X がファイルの場合、X をファイル拡張子形式でロードする。終了
2. X.js がファイルの場合、
    a. X に最も近いパッケージスコープ SCOPE を見つける。
    b. スコープが見つからなかった場合
      1. MAYBE_DETECT_AND_LOAD(X.js)
    c. SCOPE/package.json に "type" フィールドが含まれている場合、
      1. "type" フィールドが "module" の場合、X.js を ECMAScript モジュールとしてロードする。終了。
      2. "type" フィールドが "commonjs" の場合、X.js を CommonJS モジュールとしてロードする。終了。
    d. MAYBE_DETECT_AND_LOAD(X.js)
3. X.json がファイルの場合、X.json を JavaScript オブジェクトにロードする。終了
4. X.node がファイルの場合、X.node をバイナリアドオンとしてロードする。終了

LOAD_INDEX(X)
1. X/index.js がファイルの場合
    a. X に最も近いパッケージスコープ SCOPE を見つける。
    b. スコープが見つからなかった場合、X/index.js を CommonJS モジュールとしてロードする。終了。
    c. SCOPE/package.json に "type" フィールドが含まれている場合、
      1. "type" フィールドが "module" の場合、X/index.js を ECMAScript モジュールとしてロードする。終了。
      2. そうでない場合、X/index.js を CommonJS モジュールとしてロードする。終了。
2. X/index.json がファイルの場合、X/index.json を JavaScript オブジェクトとして解析する。終了
3. X/index.node がファイルの場合、X/index.node をバイナリアドオンとしてロードする。終了

LOAD_AS_DIRECTORY(X)
1. X/package.json がファイルの場合、
   a. X/package.json を解析し、"main" フィールドを探す。
   b. "main" が偽の値の場合、2. に進む。
   c. M = X + (json main フィールド) とする
   d. LOAD_AS_FILE(M)
   e. LOAD_INDEX(M)
   f. LOAD_INDEX(X) 非推奨
   g. "not found" をスロー
2. LOAD_INDEX(X)

LOAD_NODE_MODULES(X, START)
1. DIRS = NODE_MODULES_PATHS(START) とする
2. DIRS 内の各 DIR について:
   a. LOAD_PACKAGE_EXPORTS(X, DIR)
   b. LOAD_AS_FILE(DIR/X)
   c. LOAD_AS_DIRECTORY(DIR/X)

NODE_MODULES_PATHS(START)
1. PARTS = path split(START) とする
2. I = PARTS の数 - 1 とする
3. DIRS = [] とする
4. I >= 0 の間、
   a. PARTS[I] が "node_modules" の場合、d. に進む。
   b. DIR = path join(PARTS[0 .. I] + "node_modules") とする
   c. DIRS = DIR + DIRS とする
   d. I = I - 1 とする
5. DIRS + GLOBAL_FOLDERS を返す

LOAD_PACKAGE_IMPORTS(X, DIR)
1. DIR に最も近いパッケージスコープ SCOPE を見つける。
2. スコープが見つからなかった場合、戻る。
3. SCOPE/package.json の "imports" が null または undefined の場合、戻る。
4. `--experimental-require-module` が有効な場合
  a. CONDITIONS = ["node", "require", "module-sync"] とする
  b. そうでない場合、CONDITIONS = ["node", "require"] とする
5. MATCH = PACKAGE_IMPORTS_RESOLVE(X, pathToFileURL(SCOPE),
  CONDITIONS) <a href="esm#resolver-algorithm-specification">ESM レゾルバで定義されている</a> とする。
6. RESOLVE_ESM_MATCH(MATCH)。

LOAD_PACKAGE_EXPORTS(X, DIR)
1. X を、名前が @scope/ プレフィックスを持つ可能性があり、サブパスがスラッシュ ('/') で始まる NAME と SUBPATH の組み合わせとして解釈しようとする。
2. X がこのパターンに一致しない場合、または DIR/NAME/package.json がファイルでない場合、戻る。
3. DIR/NAME/package.json を解析し、"exports" フィールドを探す。
4. "exports" が null または undefined の場合、戻る。
5. `--experimental-require-module` が有効な場合
  a. CONDITIONS = ["node", "require", "module-sync"] とする
  b. そうでない場合、CONDITIONS = ["node", "require"] とする
6. MATCH = PACKAGE_EXPORTS_RESOLVE(pathToFileURL(DIR/NAME), "." + SUBPATH,
   `package.json` "exports", CONDITIONS) <a href="esm#resolver-algorithm-specification">ESM レゾルバで定義されている</a> とする。
7. RESOLVE_ESM_MATCH(MATCH)

LOAD_PACKAGE_SELF(X, DIR)
1. DIR に最も近いパッケージスコープ SCOPE を見つける。
2. スコープが見つからなかった場合、戻る。
3. SCOPE/package.json の "exports" が null または undefined の場合、戻る。
4. SCOPE/package.json の "name" が X の最初のセグメントでない場合、戻る。
5. MATCH = PACKAGE_EXPORTS_RESOLVE(pathToFileURL(SCOPE),
   "." + X.slice("name".length), `package.json` "exports", ["node", "require"])
   <a href="esm#resolver-algorithm-specification">ESM レゾルバで定義されている</a> とする。
6. RESOLVE_ESM_MATCH(MATCH)

RESOLVE_ESM_MATCH(MATCH)
1. RESOLVED_PATH = fileURLToPath(MATCH) とする
2. RESOLVED_PATH にあるファイルが存在する場合、RESOLVED_PATH をその拡張子形式でロードする。終了
3. "not found" をスロー

キャッシング

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

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

モジュールコードを複数回実行するには、関数をエクスポートしてその関数を呼び出します。

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

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

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

組み込みモジュール

[履歴]

バージョン変更
v16.0.0, v14.18.0require(...)node:インポートのサポートを追加

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

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

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

識別子がrequire()に渡された場合、一部の組み込みモジュールは常に優先的にロードされます。たとえば、require('http')は、その名前のファイルが存在する場合でも、常に組み込みの HTTP モジュールを返します。node:プレフィックスを使用せずにロードできる組み込みモジュールのリストは、module.builtinModulesでプレフィックスなしで表示されます。

node:プレフィックスが必要な組み込みモジュール

require()によってロードされる場合、一部の組み込みモジュールはnode:プレフィックスを付けて要求する必要があります。この要件は、既に名前が取得されているユーザーランドパッケージと、新しく導入された組み込みモジュールとの競合を防ぐためです。現在、node:プレフィックスを必要とする組み込みモジュールは次のとおりです。

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

サイクル

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

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

a.js:

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:

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:

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.jsb.jsをロードすると、その時点でb.jsa.jsをロードしようとします。無限ループを防ぐために、a.jsエクスポートオブジェクトの未完成のコピーb.jsモジュールに返されます。その後、b.jsのロードが完了し、そのexportsオブジェクトがa.jsモジュールに提供されます。

main.jsが両方のモジュールをロードするまでに、両方が完了しています。このプログラムの出力は次のようになります。

bash
$ 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 - レガシー]

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

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

最初の方法は、フォルダのルートに package.json ファイルを作成し、main モジュールを指定することです。package.json ファイルの例を以下に示します。

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 はデフォルトのエラーでモジュール全体が見つからないことを報告します。

bash
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('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 はそれを次のような関数ラッパーでラップします。

js
;(function (exports, require, module, __filename, __dirname) {
  // モジュールのコードはここにあります
})

これにより、Node.js はいくつかのことを実現します。

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

モジュールスコープ

__dirname

追加されたバージョン: v0.1.27

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

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

js
console.log(__dirname)
// 出力: /Users/mjr
console.log(path.dirname(__filename))
// 出力: /Users/mjr

__filename

追加されたバージョン: v0.0.1

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

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

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

例:

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

js
console.log(__filename)
// 出力: /Users/mjr/example.js
console.log(__dirname)
// 出力: /Users/mjr

2 つのモジュール ab があり、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

追加:v0.1.12

module.exportsへの参照で、より短く記述できます。exportsmodule.exportsの使い分けについては、exports ショートカットに関するセクションを参照してください。

module

追加:v0.1.16

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

require(id)

追加:v0.1.13

  • id <string> モジュール名またはパス
  • 戻り値: <any> エクスポートされたモジュールコンテンツ

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

js
// `__dirname`または現在の作業ディレクトリを基準としたパスでローカルモジュールをインポートします。(Windowsでは、これは.\path\myLocalModuleに解決されます。)
const myLocalModule = require('./path/myLocalModule')

// JSONファイルのインポート:
const jsonData = require('./path/filename.json')

// node_modulesまたはNode.js組み込みモジュールのインポート:
const crypto = require('node:crypto')

require.cache

追加:v0.3.0

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

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

js
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

追加: v0.3.0

非推奨: v0.10.6 以降

[安定度: 0 - 非推奨]

安定度: 0 安定性: 0 - 非推奨

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

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

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

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

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

require.main

追加: v0.1.17

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

entry.jsスクリプト内:

js
console.log(require.main)
bash
node entry.js
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])

[履歴]

バージョン変更点
v8.9.0pathsオプションがサポートされるようになりました。
v0.3.0追加: v0.3.0
  • request <string> 解決するモジュールパス。

  • options <Object>

    • paths <string[]> モジュール位置を解決するパス。存在する場合、これらのパスはデフォルトの解決パス($HOME/.node_modulesなどのGLOBAL_FOLDERSのようなものは常に含まれる)の代わりに使用されます。これらのパスはそれぞれ、モジュール解決アルゴリズムの開始点として使用されます。つまり、node_modules階層はこの場所からチェックされます。
  • 戻り値: <string>

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

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

require.resolve.paths(request)

追加日: v8.9.0

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

module オブジェクト

追加日: v0.1.16

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

module.children

追加日: v0.1.16

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

module.exports

追加日: v0.1.16

module.exports オブジェクトは Module システムによって作成されます。これは必ずしも許容されるものではなく、多くの場合、モジュールをあるクラスのインスタンスにしたいと考えています。そのためには、目的のエクスポートオブジェクトを module.exports に代入します。目的のオブジェクトを exports に代入すると、ローカルの exports 変数が単純に再バインドされるだけで、おそらく意図したものではありません。

例えば、a.js というモジュールを作成する場合:

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

module.exports = new EventEmitter()

// 何らかの処理を行い、しばらく後に
// モジュール自体から 'ready' イベントをemitします。
setTimeout(() => {
  module.exports.emit('ready')
}, 1000)

別のファイルでは以下のようにできます。

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

module.exports への代入は即時に行う必要があります。コールバック内では行うことができません。これは機能しません。

x.js:

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

y.js:

js
const x = require('./x')
console.log(x.a)

exports ショートカット

追加バージョン: v0.1.16

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

これにより、module.exports.f = ... をより簡潔に exports.f = ... と記述できるショートカットが実現します。ただし、変数と同様に、exports に新しい値を代入すると、module.exports にはもはやバインドされなくなることに注意してください。

js
module.exports.hello = true // モジュールの require からエクスポート
exports = { hello: false } // エクスポートされず、モジュール内でのみ使用可能

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

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

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

js
function require(/* ... */) {
  const module = { exports: {} }
  ;((module, exports) => {
    // モジュールコードはこちら。この例では、関数を定義します。
    function someFunc() {}
    exports = someFunc
    // この時点で、exports は module.exports のショートカットではなくなり、
    // このモジュールは空のデフォルトオブジェクトをエクスポートし続けます。
    module.exports = someFunc
    // この時点で、モジュールはデフォルトオブジェクトではなく、someFunc をエクスポートするようになります。
  })(module, module.exports)
  return module.exports
}

module.filename

追加バージョン: v0.1.16

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

module.id

追加バージョン: v0.1.16

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

module.isPreloading

追加バージョン: v15.4.0, v14.17.0

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

module.loaded

追加: v0.1.16

モジュールが読み込み完了済みか、読み込み中であるかを表します。

module.parent

追加: v0.1.16

非推奨: v14.6.0, v12.19.0

[安定性: 0 - 非推奨]

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

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

module.path

追加: v11.14.0

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

module.paths

追加: v0.4.0

モジュールの検索パス。

module.require(id)

追加: v0.5.1

  • id <string>
  • 戻り値: <any> エクスポートされたモジュールコンテンツ

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

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

Module オブジェクト

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

ソースマップ v3 サポート

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