Node.js で module を 作成 および 利用 する 方法

0 件のコメント

開発をしているとよく使う機能や関数、値などはモジュール化して掃き出しておきたいことがあると思います。 Node.js では module を使うことでそうしたことが実現できます。 ここでは、 module の具体的な作成方法と利用方法についてまとめます。


目次


基本的な使い方

module の 作成

module は 1ファイル として切り出して作成します。 作成したファイルにおいて module.exports にモジュール化したいオブジェクトや関数を設定することで module が作成できます。

module.js

var say = function () {
  console.log('hello');
};
module.exports = say;

module の 利用

require でモジュールファイルを指定すると module.exports に設定されたオブジェクトや関数が取り出せます。 現在のJavaScriptから見た相対パスを指定します。

program.js

var say = require('./module.js');
say();

サンプルコード

以下ではサンプルコードを見ながら具体的な使い方を見ていきます。 といっても「利用するときは require("パス") で呼び出し」 「作成するときは exports または module.exports に設定」を行うだけです。

複数メソッドのモジュール化

単純に作成した複数メソッドをモジュール化する例を以下に載せます。 複数のオブジェクトやメソッドを1つのモジュールにする場合、 exports の プロパティ を増やして追加することで出力ができます。

foo.js

var circle = require("./circle.js");
console.log(`半径 4 の 円の面積 は ${circle.area(4)}`);

circle.js

const PI = Math.PI;

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

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

この例で var circle = require("./circle.js") すると foo.js で以下のような コード を実行するのと同じ意味になります。

var circle = {
    "area": function (r) {
        return PI * r * r;
    },
    "circumference": function (r) {
        return 2 * r * PI;
    }
};

単一オブジェクトのモジュール化

単一のメソッドやクラスを出力する場合、 module.exports に対して出力したいメソッドやクラスを設定します。 先の例であげた exports に設定しても出力できません。

foo.js

var Square = require("./square.js");
var o = new Squre(2);
console.log(`1辺 が 2 の 正方形の面積 は ${o.area()}`);

square.js

var Square = function (width) {
    this.width = width;
};

Square.prototype.area = function () {
    return this.width * this.width;
};

module.exports = Square;

この例の場合、 foo.js で実行している var Square = require("./square.js") は以下のコードと同等になります。

var Square = function (width) {
    this.width = width;
};

Square.prototype.area = function () {
    return this.width * this.width;
};

[補足] module の 読み込み

読み込み順

パス Y にあるモジュールで require(X) を行った場合、以下のような読み込みを行います。

パス Y にあるモジュールで require(X) を実行

  1. X がコアモジュールの場合
    1. コアモジュールを返します
    2. 終了
  2. X.//../ で始まる場合
    1. LOAD_AS_FILE(Y + X)
    2. LOAD_AS_DIRECTORY(Y + X)
  3. LOAD_NODE_MODULES(X, dirname(Y))
  4. "not found" の例外をスロー

LOAD_AS_FILE(X)

  1. X がファイルの場合、 JavaScript テキスト として X を読み込んで終了
  2. X.js がファイルの場合、 JavaScript テキスト として X.js を読み込んで終了
  3. X.json がファイルの場合、 JavaScript オブジェクト として X.json を読み込んで終了
  4. X.node がファイルの場合、 バイナリアドオン として X.node を読み込んで終了

LOAD_AS_DIRECTORY(X)

  1. X/package.json がファイルの場合
    1. X/parse.json をパースし、mainフィールドの値を確認
    2. LOAD_AS_FILE( X/mainフィールドに指定されたファイル )
  2. X/index.js がファイルの場合、X/index.js を JavaScript として読み込んで終了
  3. X/index.json がファイルの場合、X/index.json を JavaScript として読み込んで終了
  4. X/index.node がファイルの場合、X/index.node を JavaScript として読み込んで終了

LOAD_NODE_MODULES(X, START)

  1. let DIRS = NODE_MODULES_PATHS(START)
  2. for each DIR in DIRS
    1. LOAD_AS_FILE( DIR/X )
    2. LOAD_AS_DIRECTORY( DIR/X )

NODE_MODULES_PATHS(START)

  1. let PARTS = path split(START)
  2. let I = count of PARTS - 1
  3. let DIRS = []
  4. while I >= 0,
    1. PARTS[I] が "node_modules" の場合、CONTINUE
    2. DIR = path join(PARTS[0 .. I] + "node_modules")
    3. DIRS = DIRS + DIR
    4. let I = I - 1
  5. return DIRS

キャッシュ

一度読み込まれたモジュールファイルはキャッシュされます。 複数回同じモジュールファイルを読み込もうとしても最初に読み込んだファイルのキャッシュを利用するので複数回読み込むことはありません。

参考記事