Node.js v0.11.11 マニュアル & ドキュメンテーション
Table of Contents
Modules#
Stability: 5 - Locked
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
という特別なオブジェクトに加えます。
モジュールのローカル変数は関数に包まれているかのようにプライベートになります。
この例の場合、変数 PI
は circle.js
のプライベート変数です。
モジュールのルートとして関数 (たとえばコンストラクタ) を後悔したり、
プロパティを一つずつ代入するのではなく、完全なオブジェクトを一度に
公開したければ、exports
の代わりに module.exports
に代入します。
以下では、bar.js
は square
モジュールが公開するコンストラクタを
使用しています。
var square = require('./square.js');
var mySquare = square(2);
console.log('The area of my square is ' + mySquare.area());
square.js
モジュールは square.js
で定義されています。
// assigning to exports will not modify module, must use module.exports
module.exports = function(width) {
return {
area: function() {
return width * width;
}
};
}
モジュールシステムは require("module")
モジュールによって実装されます。
Cycles#
require()
が循環的に呼び出される場合、実行が完了していないモジュールが
返されることがあります。
次の状況を考えてください:
a.js
:
console.log('a starting');
exports.done = false;
var 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;
var 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');
var a = require('./a.js');
var b = require('./b.js');
console.log('in main, a.done=%j, b.done=%j', a.done, b.done);
main.js
が a.js
をロードすると、a.js
は b.js
をロードします。
ポイントは、b.js
は a.js
のロードを試みることです。
無限ループを避けるため、a.js
がエクスポートしたオブジェクトの
未完了のコピー が 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
プログラムが循環参照するモジュールを持つ場合は、計画が適切か確認してください。
Core Modules#
Node にはバイナリにコンパイル済みのいくつかのモジュールがあります。 これらのモジュールについては、このドキュメントの他の場所でより詳しく記述されています。
コアモジュールは、 Node のソースの lib/
フォルダにて定義されています。
require()
では常にコアモジュールの識別名を優先的に解釈します。
例えば require('http')
は、例え同名のファイルが存在していたとしても、常にビルトイインの HTTP モジュールを返します。
File Modules#
指定された名前のファイルが見つからなければ、 Node は指定されたファイル名に
.js
、.json
、または .node
を付けたものを読み込もうとします。
.js
ファイルは JavaScript ファイルとして解釈され、
.json
ファイルは JSON ファイルとして解釈されます。
一方 .node
ファイルはコンパイル済みのアドオンモジュールとして解釈され、
dlopen
を使って読み込まれます。
'/'
から始まるモジュールは、ファイルへの絶対パスと見なされます。
例えば、 require('/home/marco/foo.js')
は /home/macro/foo.js
を読み込みます。
'./'
から始まるモジュールは、 require()
を呼んだファイルからの相対パスになります。
すなわち、 foo.js
から require('./circle')
によって circle.js
を読み込むには、 circle.js
は foo.js
と同じディレクトリに存在していなければなりません。
'/' や './' が先頭になければ、モジュールは "コアモジュール" であるかもしくは node_modules
フォルダから読み込まれることになります。
与えられたパスが存在しなかった場合、require()
は code
プロパティに
'MODULE_NOT_FOUND'
を設定したエラーをスローします。
Loading from node_modules
Folders#
もし require()
に渡されたモジュール識別子がネイティブモジュールではなく、かつ '/'
や '../'
や './'
から始まらないならば、 Node は現在のモジュールの親ディレクトリに '/node_modules'
を付与してそこからモジュールを読み込もうとします。
そこに見つからない場合はさらに親ディレクトリに移動し、モジュールが見つかるか root ディレクトリに到達するまで同様のことを繰り返していきます。
例えば '/home/ry/projects/foo.js'
の中で require('bar.js')
を呼んでいた場合、 Node は下記の位置を上から順番に見ていきます。
/home/ry/projects/node_modules/bar.js
/home/ry/node_modules/bar.js
/home/node_modules/bar.js
/node_modules/bar.js
この仕組みによって、プログラムはクラッシュを避けるために依存関係を上書きすることができるのです。
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')
は以下のファイルを読み込もうとします:
./some-library/index.js
./some-library/index.node
Caching#
モジュールは初めて読み込まれたときにキャッシュされます。
すなわち(他のキャッシュと同様に) require('foo')
を呼ぶたびに、もし引数の意味するものが同一のファイルであったなら全く同一のオブジェクトが返されます。
require('foo')
が複数回呼び出されても、モジュールが複数回実行されることにはなりません。
これは重要な特徴です。
そのため、「部分的に完了した」オブジェクトを返すことで、
推移的な依存関係が循環していてもロードすることができます。
もしモジュールを複数回実行したければ、関数を公開して、 その関数を呼び出してください。
Module Caching Caveats#
モジュールは解決されたファイル名に基づいてキャッシュされます。
異なる場所にあるモジュールから呼び出されたモジュールは、
(node_module
フォルダからロードされるため) 異なったファイル名で
解決されることがあるため、 require('foo')
が常に同じオブジェクトを返す
保証はなく、異なるファイルとして解決されます。
The module
Object#
!-- name=module -->
- {Object}
どのモジュールでも、module
自由変数は現在のモジュールを表現するオブジェクトを
参照します。
利便性のため、module.exports
は exports
オブジェクトを通じて
参照することもできます。
module
は実際はグローバルではなく、各モジュールのローカル変数です。
module.exports#
- Object
module.exports
オブジェクトはモジュールシステムによって作成されます。
時々これは受け入れらません;
多くの人々は、モジュールが何らかのクラスのインスタンスであることを望みます。
それには、公開したいオブジェクトを module.exports
に割り当てます。
望ましいオブジェクトを exports
へ代入することは、ローカル変数 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);
exports alias#
モジュール内で利用出来る exports
変数は、最初は module.exports
への参照です。
他の変数と同様、それに新しい値を割り当てると元の値はもはや束縛されません。
その振る舞いを示すために、この仮定の実装を想像してください。
function require(...) {
// ...
function (module, exports) {
// Your module code here
exports = some_func; // re-assigns exports, exports is no longer
// a shortcut, and nothing is exported.
module.exports = some_func; // makes your module export 0
} (module, module.exports);
return module;
}
ガイドラインとして、もし exports
と module.exports
の間の関係が魔法のように
見えるなら、exports
を無視して module.exports
だけを使うようにしてください。
module.require(id)#
id
{String}- Return: {Object} 解決されたモジュールの
module.exports
module.require
メソッドは、元のモジュールが require()
を呼び出したかのようにモジュールをロードするために提供されています。
それには module
オブジェクトの参照が必要なことに注意してください。
require()
が module.exports
を返した後、一般的に module
はそのモジュールのコードで のみ 利用可能です。
それが使われるようにするには、明示的にエクスポートする必要があります。
module.id#
- String
モジュールの識別子。通常は完全に解決されたファイル名です。
module.filename#
- String
完全に解決されたモジュールのファイル名です。
module.loaded#
- Boolean
モジュールのロードが完了したか,あるいはローディング中かを示します。
module.parent#
- Module Object
このモジュールを要求したモジュールです。
module.children#
- Array
このモジュールが要求したモジュールです。
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. If X/index.js is a file, load X/index.js as JavaScript text. STOP
3. If X/index.node is a file, load X/index.node as binary addon. STOP
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 global folders#
NODE_PATH
環境変数に絶対パスをコロンで区切ったリストを設定すると、
node は他で見つからなかったモジュールをそれらのパスから探します。
(注意: Windows では、NODE_PATH
はコロンではなくセミコロンで区切られます)
加えると、node は以下の場所から検索します。
- 1:
$HOME/.node_modules
- 2:
$HOME/.node_libraries
- 3:
$PREFIX/lib/node
$HOME
はユーザのホームディレクトリ、$PREFIX
は node を
configure した時の node_prefix
です。
これらは主に歴史的な理由によるものです。
あなたが依存するものはローカルの node_modules
フォルダに置くことが
強く推奨されます。それは素早くロードされ、確実です。
Accessing the main module#
ファイルがNodeによって直接実行される場合、その module
が
require.main
に設定されます。
これは、ファイルが直接実行されたかを決定できることを意味します。
require.main === module
foo.js
ファイルの場合、node foo.js
と実行された場合にこれは true
になりますが、require('./foo')
で実行された場合は false
になります。
module
は filename
プロパティ (通常 __filename
と同じです)
を提供するため、現在のアプリケーションのエントリポイントは
require.main.filename
をチェックすることで得ることができます。
Addenda: Package Manager Tips#
Node の require()
は普通のディレクトリ構造をサポートできるよう汎用的に設計されています。
dpkg
や rpm
や npm
のようなパッケージ管理プログラムは修正なしに Node モジュールからネイティブパッケージを組み立てることができるでしょう。
推奨するディレクトリ構造は次のようになります:
例えば /usr/lib/node/<some-package>/<some-version>
フォルダに、あるパッケージの特定のバージョンを保持する形式です。
パッケージは相互に依存しあうことがあります。
foo
パッケージをインストールするためにはある特定のバージョンの bar
パッケージをインストールする必要があります。
bar
パッケージ自身も依存関係をもっているので、ときには依存関係が衝突したり循環したりすることがあります。
Node はモジュールの realpath
(シンボリックリンクを解釈します)を調べ、その依存関係を上述の node_modules
フォルダの仕組みで探しにいきます。
これによって次のような構造をとてもシンプルに解釈することができます。
/usr/lib/node/foo/1.2.3/
-foo
パッケージの中身。バージョン1.2.3。/usr/lib/node/bar/4.3.2/
-bar
パッケージの中身。foo
が依存している。/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 は見つからない依存パッケージを /usr/node_modules
や /node_modules
に探しにいかなくてもようなります。
Node の REPL でモジュールを使えるようにするために、 /usr/lib/node_modules
フォルダを $NODE_PATH
環境変数に追加するとよいでしょう。
node_modules
フォルダを使ったモジュール探索は全て相対的なものであり、 require()
を呼び出したファイルの絶対パスを基準としているので、パッケージ自体はどこにでも配置することができます。