モジュールの読み込み優先度
http://nodejs.jp/nodejs.org_ja/docs/v0.4/api/modules.html#loading_from_node_modules_Folders
この項に書いている話ですべてではあるものの改めて書くと、
ある js ファイル上で require() を使ってモジュールを読み込もうとする際、指定した path が「/」「./」「../」といった指定の仕方ではないならば、その js ファイルからルートまでのすべてのパス上に存在する *node_modules* というディレクトリ内がモジュール読み込み対象となる。もちろん、深いレベル (読み込み元 js ファイルに近い) ほど優先度が高い。
/path/to/app/app.jp で require() したならば、次に示す順のディレクトリ内モジュールが検索される。
- /path/to/app/node_modules
- /path/to/node_modules
- /path/node_modules
- /node_modules
もちろん、require() で指定する path が階層構造でも問題なし。上の例で、require('my/app/foo_module.js') という指定をしたならば、モジュールとしてのファイルは以下のように検索される。
- /path/to/app/node_modules/my/app/foo_module.js
- /path/to/node_modules/my/app/foo_module.js
- /path/node_modules/my/app/foo_module.js
- /node_modules/my/app/foo_module.js
基本的にはこれさえ分かっていれば、容易に共有/固有のモジュール領域が作れる。
ソフトウェアごとのモジュール配置
私は現在のところ、Nodeで開発しているソフトウェア (ex: foo_project) のモジュール配置は次のように行っている。
- foo_project - app - app.js - node_modules - (ソフトウェア固有ドメインのモジュール) - node_modules - (npm 等で導入される共有モジュール) - (node_modules)
foo_project として実装されたソースは app ディレクトリ以下に配置、実行するようにし、直下にそのソフトウェア固有ドメイン向けのモジュール領域を作成する。開発したドメインモデル等はすべてこの app/node_modules 以下に設置する。
一方、npm 等で配布されているパッケージや会社資産などのライブラリモジュール (これも package として社内配布するとよい) は、先ほどの固有ドメイン向けの領域より一段上に配置する。本質的には読み込み優先順位を下げる必要はないが、ツリー自体の可読性と固有ドメインとの分別説明のために明確な分離を行う。
なおこれ以上分離が必要な場合は、さらにその上位にモジュールディレクトリを準備する。分離したい数だけ、上位ディレクトリに node_modules ディレクトリを作成すればよい。制限はただ一つ、ルートディレクトリにたどり着くまで。
npm による任意モジュールディレクトへのパッケージ導入
目的の node_modules ディレクトリへ移動した後に npm install を行えば、そのディレクトリへパッケージを導入できる。
npm は現在のところ対象となる node_modules 内パッケージディレクトリの内容のみで管理しているように思われるため、目的のディレクトリ内におけるパッケージの追加や削除も容易に行うことができる。
「require.paths」の削除
以前は require.paths という組み込み配列に任意のパスを push することで、モジュールの読み込み対象ディレクトリを増やすことができた。しかし、現在ベータバージョンである v0.5 系では削除されている。元々 v0.4 系リリース時点のドキュメントで「いつか消すから止めとけ」という明記がされていて、いつ完全削除されるものかと思っていたものの、案外早く対処されたという印象。
コード上から容赦なくパスを操作できてしまうのはトラブルの元だし不安定な挙動を引き起こす可能性が高いということで、なくなって正解だったと思われる。何より、現在の仕組みはシンプルながらも強力で融通も利く。