Node.js モジュール分割についてのメモ


node.jsのモジュールについて、動作を確認してみました。 こんな処にも、ノンブロッキングI/Oの実行モデルの影響があるんですね。 しっかり頭を切り替えて考えないと、バグを埋め込んでしまいます。


## モジュールの関数をアクセスする

~~~js:test1a.js
#!/usr/bin/env node

var app = require('./mod1a');

console.log("app.abc = ", app.abc(1, 2));
console.log("app.xyz = ", app.xyz(2, 3));
~~~

関数名をexportsするには、次の書き方になります。

~~~js:mod1a.js
exports.abc = function(a, b) {
    return a + b;
};

exports.xyz = function(a, b) {
    return a * b;
};
~~~

### 実行結果

~~~
$ ./test1a.js 
app.abc =  3
app.xyz =  6
~~~


### もう一つの書き方
読み難くなりますが、functionを省略して、スッキリ書くこともできます。

~~~js:mod1b.js
exports.abc = (a, b) => a + b;
exports.xyz = (a, b) => a * b;
~~~

コールの方法は同じです。

~~~js:test1b.js
#!/usr/bin/env node

var app = require('./mod1b');

console.log("app = ", app.abc(1, 2));
console.log("app = ", app.xyz(2, 3));
~~~

### もう一つの書き方の実行結果

~~~
$ ./test1b.js
app =  3
app =  6
~~~

### さらにカッコを使った書き方
複数行の処理を書きたい場合は、{}カッコで括ることができます。

~~~js:mod1c.js
exports.abc = (a, b) => {
    c = a + b;
    return c;
}
exports.xyz = (a, b) => {
    c = a * b;
    return c;
}
~~~


## モジュールのオブジェクトにアクセスする
変数を次の書き方で、エクスポートできます。

~~~js:mod2.js
var x = 100;
module.exports = x;
~~~


~~~js:test2.js
#!/usr/bin/env node

var app = require('./mod2');
console.log("app = ", app);
~~~

### 実行結果

~~~
$ ./test2.js
app =  100
~~~



## モジュールにモジュールを与えて実行する
前述のmod1をmod3に与えて実行するものです。

~~~js:test3.js
#!/usr/bin/env node

var app1 = require('./mod1');
var app3 = require('./mod3')(app1);

console.log("app = ", app3);
~~~

~~~js:mod3.js
module.exports = function(app) {
    return app.abc(3, 4);
};
~~~


### 実行結果

~~~
$ ./test3.js 
app =  7
~~~


## モジュールでメインを判別する
require.main === module が false であれば、モジュールとして呼び出されている事を表し、true であればモジュール自身が、ダイレクトに実行されている。

~~~js:mod4.js
exports.abc = function(a, b) {
    return a + b;
};


if (require.main === module) {
    console.log("result = ", exports.abc(1, 2));
}
~~~


~~~js:test4.js
#!/usr/bin/env node

var app = require('./mod4');

console.log("app = ", app.abc(4, 5));
~~~

### 実行結果
次の前半が、ダイレクトに実行、後半がメインモジュールから実行されるケース

~~~
$ node mod4.js 
main =  true
result =  29

$ ./test4.js 
main =  false
app =  9
~~~


## モジュールの多重取り込みのケース
mod7a.js のモジュールから、mod7b.js モジュールを読み込みます。

~~~js:mod7a.js
console.log('a starting');
exports.done = false;
const b = require('./mod7b.js');
console.log('in a, b.done = %j', b.done);
exports.done = true;
console.log('a done');
~~~

一方、mod7b.js モジュールは、mod7a.jsモジュールを読み込みます。

~~~js:mod7b.js
console.log('b starting');
exports.done = false;
const a = require('./mod7a.js');
console.log('in b, a.done = %j', a.done);
exports.done = true;
console.log('b done');
~~~


メインのモジュールからは、mod7a,mod7b を順番に取り込みます。

~~~js:test7.js
#!/usr/bin/env node

console.log('main starting');
const a = require('./mod7a.js');
const b = require('./mod7b.js');
console.log('in main, a.done=%j, b.done=%j', a.done, b.done);
~~~

### 実行結果
メッセージのmod7a の読み込みと実行を待たずに、mod7b が読み込まれ実行を開始して、mod7bの終了後に、mod7a が実行されています。おそらく、平行で動作していると考えても良いと思います。 モジュールを取り込む場合、逐次実行ではなく、平行実行である事に注意する必要がありますね。

~~~
$ ./test7.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
~~~

# 参考資料

(1) Node.js v6.11.1 Documentation Modules https://nodejs.org/dist/latest-v6.x/docs/api/modules.html#modules_accessing_the_main_module