モジュール化とグローバル変数

最近のexpressは、コールバックルーチンをモジュール化して、routesディレクトリに置くような作りになっているようです。使いづらいと批判も結構あるみたいですが、一つのファイルが大きくなりすぎるのはどうかと思うので、個人的には自然な流れかなと。

さて、ここで問題が発生。基本的に変数のスコープはモジュール内のみのため、モジュール化してrequireで呼び出すコールバックルーチンではメインのモジュール(app.js)で宣言した変数が使えません。

例えばapp.jsでmongoDBのモデルを作成して、コールバックルーチンでそのモデルを使いたい場合に、各モジュールからこのモデルにアクセス出来ません。引数として渡す方法もありますが、expressを使う場合はコールバック関数の引数が予め決まっているため、この方法は使えませんね。

こんな時は、各モジュールでシェアする変数用のモジュールを作りましょう。

上記のように、libディレクトリにshare.jsファイルを作成(ディレクトリ名とファイル名はなんでもいいです)します。各モジュールから、このshare.jsファイルをrequireで呼ぶことで、そのモジュールに定義した変数にアクセスが可能となります^ ^

さてさて、ここで忘れてはいけないのがモジュール機構。Node.jsはcommonJSの仕様に従っていて、モジュール機構が使えるとかなんとか。細かいことはよく知りませんが、要はプログラム内で使用可能な環境変数が設定出来るとのこと。C出身の私としては、今間でなかったんだ。。。って感じだけど^ ^;

上記図をよ〜くみると気づくと思いますが、share.jsのパスを指定していません。requireには2つの指定方法があって、パスを直接指定する方法(上記のtest.jsの読み込みなど)と、モジュール機構を使う方法とがあります。share.jsはいろんなファイルから読み込みたいので、いちいちパスとか考えたくないですね。ってことで、NODE_PATHにパスを追加します。

NODE_PATH=$NODE_PATH:lib node app.js

こんな感じ。でも毎回こんなの書くの面倒ですね。ってことで、expressが自動で作ってくれるpackage.jsonを使いましょう。このファイルのscriptsに、以下のように記述します。

{
"name": "application-name"
, "version": "0.0.1"
, "private": true
, "dependencies": {
"express": "2.5.1"
, "ejs": ">= 0.0.1"
}
, "scripts": {
"start": "NODE_PATH=$NODE_PATH:lib node app.js"
}
}

青字の部分以外はexpressが自動で作成しています。scriptsのstartに、置き換えたいコマンドを記入します。これもまた環境変数みたいな感じですね。

ってことで、このファイル編集した上で、以下のようにコマンド実施してみましょう。

[ec2-user@ip-10-117-93-66 rest_app]$ npm start

> application-name@0.0.1 start /home/ec2-user/node4dreampass/test/rest_app
> NODE_PATH=$NODE_PATH:lib node app.js

Server listening on port 3000 in development mode

出来た!