Node.js v0.4.12 Manual & Documentation


Table Of Contents


Standard Modules

Node は多くのコンパイル済みのモジュールを備えています。 そのうちの多くは以降のドキュメントに記述されています。 モジュールを使用するもっとも一般的な方法は、 require('name') を呼びその戻り値をモジュールと同名のローカル変数に代入することです。

例:

var util = require('util');

標準モジュール以外のモジュールを用いて Node を拡張することがでいます。 'Modules' をご覧ください。

Modules

Node はシンプルなモジュールローディングシステムを持ちます。 Node では、ファイルとモジュールは1対1に対応します。 例として、 foo.js は、同じディレクトリにある circle.js をロードしています。

foo.js の内容:

var circle = require('./circle.js');
console.log( 'The area of a circle of radius 4 is '
           + circle.area(4));

circle.js の内容:

var PI = Math.PI;

exports.area = function (r) {
  return PI * r * r;
};

exports.circumference = function (r) {
  return 2 * PI * r;
};

circle.js モジュールは area()circumference() をエクスポートしています。 オブジェクトをエクスポートするには、 exports という特別なオブジェクトに加えます。 モジュールのローカル変数はプライベートです。 この例の場合、変数 PIcircle.js のプライベート変数です。

Core Modules

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

コアモジュールは、 Node のソースの lib/ フォルダにて定義されています。

require() では常にコアモジュールの識別名を優先的に解釈します。 例えば require('http') は、例え同名のファイルが存在していたとしても、常にビルトイインの HTTP モジュールを返します。

File Modules

指定された名前のファイルが見つからなかったら、 Node は指定されたファイル名に .js を付けたものと .node を付けたものを読み込もうとします。

.js ファイルは JavaScript ファイルとして解釈されます。 一方 .node ファイルはコンパイル済みのアドオンモジュールとして解釈され、 dlopen を使って読み込まれます。

'/' から始まるモジュールは、ファイルへの絶対パスと見なされます。 例えば、 require('/home/marco/foo.js')/home/macro/foo.js を読み込みます。

'./' から始まるモジュールは、 require() を呼んだファイルからの相対パスになります。 すなわち、 foo.js から require('./circle') によって circle.js を読み込むには、 circle.jsfoo.js と同じディレクトリに存在していなければなりません。

'/' や './' が先頭になければ、モジュールは "コアモジュール" であるかもしくは node_modules フォルダから読み込まれることになります。

Loading from `node_modules` Folders

もし require() に渡されたモジュール識別子がネイティブモジュールではなく、かつ '/''../''./' から始まらないならば、 Node は現在のモジュールの親ディレクトリに '/node_modules' を付与してそこからモジュールを読み込もうとします。

そこに見つからない場合はさらに親ディレクトリに移動し、モジュールが見つかるか root ディレクトリに到達するまで同様のことを繰り返していきます。

例えば '/home/ry/projects/foo.js' の中で require('bar.js') を呼んでいた場合、 Node は下記の位置を上から順番に見ていきます。

この仕組みによって、プログラムはクラッシュを避けるために依存関係を上書きすることができるのです。

Folders as Modules

プログラムとライブラリをディレクトリ内にまとめて、そのエントリポイントを提示するという便利な方法もあります。 それには require() に引数として何を渡すかによって3通りの方法があります。

1つ目は、 package.json というファイルをフォルダ直下に作成し、 main モジュールを指定するという方法です。 例えば、 package.json は以下のようなファイルになります:

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

もし ./some-library フォルダ内にこのファイルがあれば、 require('./some-library')./some-library/lib/some-library.js を読みにいきます。

これは、 Node が package.json の存在に気づくことによってもたらされます。

もし package.json がディレクトリに存在していなければ、 Node はそのディレクトリで index.js もしくは index.node を探します。 例えば、もし上の例で package.json がいるが存在しないとすると、 require('./some-library') は以下のファイルを読み込もうとします:

Caching

モジュールは初めて読み込まれたときにキャッシュされます。 すなわち(他のキャッシュと同様に) require('foo') を呼ぶたびに、もし引数の意味するものが同一のファイルであったなら全く同一のオブジェクトが返されます。

require('foo') が複数回呼び出されても、モジュールが複数回実行されることにはなりません。 これは重要な特徴です。 そのため、「部分的に完了した」オブジェクトを返すことで、 推移的な依存関係が循環していてもロードすることができます。

もしモジュールを複数回実行したければ、関数を公開して、 その関数を呼び出してください。

Module Caching Caveats

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

module.exports

exports オブジェクトはモジュールシステムによって作成されます。 時々これは受け入れられず、多くのモジュールは何らかのクラスのインスタンスであることを望みます。 それには公開したいオブジェクトを module.exports に割り当てます。 例えば a.js と呼ばれるモジュールを作るとしたら

var EventEmitter = require('events').EventEmitter;

module.exports = new EventEmitter();

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

そして別のファイルで

var a = require('./a');
a.on('ready', function() {
  console.log('module a is ready');
});

module.exports への代入はすぐに行わなければなりません。 コールバックの中ではできません。以下は動きません。

x.js:

setTimeout(function() {
  module.exports = { a: "hello" };
}, 0);

y.js:

var x = require('./x');
console.log(x.a);

All Together...

require() が呼び出されると、正確なファイル名を得るために require.resolve() が使われます。

上で述べたことをまとめると、 require.resolve は以下の擬似コードで記述されるようなハイレベルなアルゴリズムに則っています:

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 './' or '/' or '../'
   a. LOAD_AS_FILE(Y + X)
   b. LOAD_AS_DIRECTORY(Y + X)
3. LOAD_NODE_MODULES(X, dirname(Y))
4. THROW "not found"

LOAD_AS_FILE(X)
1. If X is a file, load X as JavaScript text.  STOP
2. If X.js is a file, load X.js as JavaScript text.  STOP
3. If X.node is a file, load X.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. let M = X + (json main field)
   c. LOAD_AS_FILE(M)
2. LOAD_AS_FILE(X/index)

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

NODE_MODULES_PATHS(START)
1. let PARTS = path split(START)
2. let ROOT = index of first instance of "node_modules" in PARTS, or 0
3. let I = count of PARTS - 1
4. let DIRS = []
5. while I > ROOT,
   a. if PARTS[I] = "node_modules" CONTINUE
   c. DIR = path join(PARTS[0 .. I] + "node_modules")
   b. DIRS = DIRS + DIR
   c. let I = I - 1
6. return DIRS

Loading from the `require.paths` Folders

require.paths は、指定されたモジュール名が '/''./''../' から始まっていないときにモジュールを探しにいくパスを文字列として保持している配列です。 例えば、require.pathsが次のように設定されているとします:

[ '/home/micheil/.node_modules',
  '/usr/local/lib/node_modules' ]

そして、 require('baz/baz.js') を呼ぶと次の場所を探しにいきます:

これらの動作を修正することができるよう、 require.paths 配列は実行時に変更することができます。

require.pathsNODE_PATH という環境変数の値によって初期化されます。 NODE_PATH にはコロンで区切った複数のパスを記述することができます。 上の例では、 NODE_PATH には次のような値がセットされていたものと考えられます:

/home/micheil/.node_modules:/usr/local/lib/node_modules

require.paths からロードされるのは、モジュールが前述の node_modules アルゴリズムで見つけられなかった場合だけです。 グローバルモジュールはバンドルされた依存性よりも低プライオリティです。

**Note:** Please Avoid Using `require.paths`

require.paths は安定版である v0.4 の終わりまでしかサポートされません。 Node v0.5 からは削除されました。

実装当時はよいアイデアだと思われ実験的に使う分にはとても有用でしたが、実際に使いだしてみると変更可能な require.paths のリストというものはやっかいな混乱と頭痛の種になることがしばしばあったのです。

Setting `require.paths` to some other value does nothing.

次のコードは、希望通りには動きません:

require.paths = [ '/usr/lib/node' ];

これは、 実際の Node モジュールへの参照パスを消滅させ、使われることのないパスに対する新たな参照を作り出しています。

Putting relative paths in `require.paths` is... weird.

次のようにするとします:

require.paths.push('./lib');

これは、ファイルシステム上の ./lib のある場所への絶対パスを追加する わけではありません 。 代わりに、文字通り './lib' を追加します。 すなわち、もし /a/b/x.js ファイル内で require('y.js') した場合、 /a/b/lib/y.js を探しにいきます。 同様に /l/m/n/o/p.js ファイル内で require('y.js') した場合は、 /l/m/n/o/lib/y.js を探しにいきます。

実際に、これらはアドホックな依存性をバンドルするために用いられています。 しかしこれらのテクニックはとても不安定です。

Zero Isolation

(残念なことに)たった一つの require.paths 配列が全てのモジュールによって使われるという設計になっています。

その結果、もしある Node プログラムが上記の挙動を行っていたら、同じプロセス上にいる他の全ての Node プログラムの動作も永遠にそして微妙に変化させてしまいます。 アプリケーションが成長するにつれ、私たちは機能をまとめていきますが、 それらがどのように影響するかを予測するのが難しくなります。

Accessing the main module

ファイルがNodeによって直接実行される場合、その modulerequire.main に設定されます。 これは、ファイルが直接実行されたかを決定できることを意味します。

require.main === module

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

modulefilename プロパティ (通常 __filename と同じです) を提供するため、現在のアプリケーションのエントリポイントは require.main.filename をチェックすることで得ることができます。

Addenda: Package Manager Tips

Node の require() は普通のディレクトリ構造をサポートできるよう汎用的に設計されています。 dpkgrpmnpm のようなパッケージ管理プログラムは修正なしに Node モジュールからネイティブパッケージを組み立てることができるでしょう。

推奨するディレクトリ構造は次のようになります:

例えば /usr/lib/node/<some-package>/<some-version> フォルダに、あるパッケージの特定のバージョンを保持する形式です。

パッケージは相互に依存しあうことがあります。 foo パッケージをインストールするためにはある特定のバージョンの bar パッケージをインストールする必要があります。 bar パッケージ自身も依存関係をもっているので、ときには依存関係が衝突したり循環したりすることがあります。

Node はモジュールの realpath (シンボリックリンクを解釈します)を調べ、その依存関係を上述の node_modules フォルダの仕組みで探しにいきます。 これによって次のような構造をとてもシンプルに解釈することができます。

このようにして、もし仮に依存関係に循環や衝突が見つかったとしても、全てのモジュールは依存しているパッケージの特定のバージョンを取得することができます。

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 は見つからない依存パッケージを /usr/node_modules/node_modules に探しにいかなくてもようなります。

Node の REPL でモジュールを使えるようにするために、 /usr/lib/node_modules フォルダを $NODE_PATH 環境変数に追加するとよいでしょう。 node_modules フォルダを使ったモジュール探索は全て相対的なものであり、 require() を呼び出したファイルの絶対パスを基準としているので、パッケージ自体はどこにでも配置することができます。