Node.jsのモジュール機能について
Follow @venividivici830
Node.jsのモジュール機能について学習した。
モジュール機能は、サーバーサイドJavaScriptの標準APIの仕様を定めるプロジェクトであるCommonJSでも、早い時期から規格化と実装が進んでいたようだ。
モジュールは、プログラムのソース・ファイルを複数ファイルに分けて管理し、名前空間を分離することを可能にする、Node.js自体が提供する言語機能である。
Nodeのバージョンは、
まずは、モジュールとして利用される側。
Animal.js
モジュールとして利用する側は、require関数を使う。
require関数の引数には、ファイル名を指定する。ファイル名の.jsは省略できる。
main.js
実行すると、特にエラーなく処理が終了する。
Animal.js
moduleオブジェクトのプロパティが一覧された。
exportsプロパティの存在が確認できる。
parentプロパティには、モジュールを呼び出している側のmoduleオブジェクトが格納されるようだ。
pathsプロパティには、モジュールを探すパスの配列が設定されているようだ。
基本的に、node_modulesというディレクトリーを親ディレクトリーに向かって探していくようだ。
注目すべきは、pathsプロパティの配列に、カレントディレクトリーが含まれていないことである。
よって、下記のコードはエラーとなる。
下記の構成にすれば、node_modulesはモジュールを探すパスであるため、上記のコードでも問題ない。
main.js
require関数のプロパティが一覧された。
mainプロパティは、メインとして実行されたスクリプトのmoduleオブジェクトが格納されるようだ。
よって、下記のコードは、メインとして実行されたスクリプトではtrueとなる。
main.js
利用されるモジュール側でも確認すると、確かにrequire.mainには、メインとして実行されたスクリプトであるmain.jsのmoduleオブジェクトが格納されている。
Animal.js
このように、メインとして実行されたスクリプトを特定できる。
Node.jsのモジュール機能について学習した。
モジュール機能は、サーバーサイドJavaScriptの標準APIの仕様を定めるプロジェクトであるCommonJSでも、早い時期から規格化と実装が進んでいたようだ。
モジュールは、プログラムのソース・ファイルを複数ファイルに分けて管理し、名前空間を分離することを可能にする、Node.js自体が提供する言語機能である。
Nodeのバージョンは、
$ node -v
v10.9.0
モジュールのエクスポートとインポート
下記の構成で、2つのファイルを使って検証した。
$ pwd
/Users/user/Desktop/node_test
$ ls
Animal.js main.js
まずは、モジュールとして利用される側。
moduleという名前のオブジェクトが、最初から存在する。
moduleオブジェクトのexportsプロパティが参照するオブジェクトのプロパティに、エクスポートするオブジェクトを設定することで、オブジェクトをエクスポートできる。
Animal.js
var Animal = function() {}
module.exports.Animal = Animal;
モジュールとして利用する側は、require関数を使う。
require関数の引数には、ファイル名を指定する。ファイル名の.jsは省略できる。
main.js
var lib = require('./Animal')
var animal = new lib.Animal();
当然下記のようにも書ける。
var Animal = require('./Animal').Animal;
var animal = new Animal();
$ node main.js
モジュールは、デフォルトでグローバルの名前空間を汚染しない。
下記のように、エクスポートしない場合は、別のファイルから見えない。
Animal.js
var Animal = function() {}
// module.exports.Animal = Animal;
$ node main.js
TypeError: lib.Animal is not a constructor
module以外に、exportsという名前のオブジェクトも、最初から存在する。
下記のコードでtrueが出力されることが示すように、module.exportsとexportsは、同じオブジェクトを参照している。
console.log(module.exports === exports)
従って、下記のようにも書ける。
Animal.js
exports.Animal = Animal;
moduleオブジェクト
console.debugで、moduleオブジェクトについて、詳しく見てみた。
Animal.js
var Animal = function() {}
module.exports.Animal = Animal;
console.debug(module)
$ node main.js
Module {
id: '/Users/user/Desktop/node_test/Animal.js',
exports: { Animal: [Function: Animal] },
parent:
Module {
id: '.',
exports: {},
parent: null,
filename: '/Users/user/Desktop/node_test/main.js',
loaded: false,
children: [ [Circular] ],
paths:
[ '/Users/user/Desktop/node_test/node_modules',
'/Users/user/Desktop/node_modules',
'/Users/user/node_modules',
'/Users/node_modules',
'/node_modules' ] },
filename: '/Users/user/Desktop/node_test/Animal.js',
loaded: false,
children: [],
paths:
[ '/Users/user/Desktop/node_test/node_modules',
'/Users/user/Desktop/node_modules',
'/Users/user/node_modules',
'/Users/node_modules',
'/node_modules' ] }
moduleオブジェクトのプロパティが一覧された。
exportsプロパティの存在が確認できる。
parentプロパティには、モジュールを呼び出している側のmoduleオブジェクトが格納されるようだ。
pathsプロパティには、モジュールを探すパスの配列が設定されているようだ。
基本的に、node_modulesというディレクトリーを親ディレクトリーに向かって探していくようだ。
注目すべきは、pathsプロパティの配列に、カレントディレクトリーが含まれていないことである。
よって、下記のコードはエラーとなる。
var Animal = require('Animal').Animal;
$ node main.js
Error: Cannot find module 'Animal'
下記の構成にすれば、node_modulesはモジュールを探すパスであるため、上記のコードでも問題ない。
.
├── main.js
└── node_modules
└── Animal.js
require関数
console.debugで、require関数について、詳しく見てみた。main.js
var Animal = require('Animal').Animal;
var animal = new Animal();
console.debug(require)
$ node main.js
{ [Function: require]
resolve: { [Function: resolve] paths: [Function: paths] },
main:
Module {
id: '.',
exports: {},
parent: null,
filename: '/Users/user/Desktop/node_test/main.js',
loaded: false,
children: [ [Module] ],
paths:
[ '/Users/user/Desktop/node_test/node_modules',
'/Users/user/Desktop/node_modules',
'/Users/user/node_modules',
'/Users/node_modules',
'/node_modules' ] },
extensions:
{ '.js': [Function], '.json': [Function], '.node': [Function] },
cache:
{ '/Users/user/Desktop/node_test/main.js':
Module {
id: '.',
exports: {},
parent: null,
filename: '/Users/user/Desktop/node_test/main.js',
loaded: false,
children: [Array],
paths: [Array] },
'/Users/user/Desktop/node_test/node_modules/Animal.js':
Module {
id: '/Users/user/Desktop/node_test/node_modules/Animal.js',
exports: [Object],
parent: [Module],
filename: '/Users/user/Desktop/node_test/node_modules/Animal.js',
loaded: true,
children: [],
paths: [Array] } } }
require関数のプロパティが一覧された。
mainプロパティは、メインとして実行されたスクリプトのmoduleオブジェクトが格納されるようだ。
よって、下記のコードは、メインとして実行されたスクリプトではtrueとなる。
main.js
console.debug(require.main === module)
$ node main.js
true
利用されるモジュール側でも確認すると、確かにrequire.mainには、メインとして実行されたスクリプトであるmain.jsのmoduleオブジェクトが格納されている。
Animal.js
var Animal = function() {}
module.exports.Animal = Animal;
console.debug(require.main === module)
console.debug(require)
$ node main.js
false
{ [Function: require]
resolve: { [Function: resolve] paths: [Function: paths] },
main:
Module {
id: '.',
exports: {},
parent: null,
filename: '/Users/user/Desktop/node_test/main.js',
loaded: false,
children: [ [Module] ],
paths:
[ '/Users/user/Desktop/node_test/node_modules',
'/Users/user/Desktop/node_modules',
'/Users/user/node_modules',
'/Users/node_modules',
'/node_modules' ] },
extensions:
以下省略...
このように、メインとして実行されたスクリプトを特定できる。
コメント
コメントを投稿