Node.jsで絶対パスでモジュールを読み込む方法についてです。Node.jsでは相対パスでモジュール、外部ファイルを読み込むことはできますが、絶対パスで読み込むためには少し工夫をする必要があります。
先日までは以下のようなフォーマットで外部モジュールをrequireしていました。これでうまく行っているように見えていました。しかし。
var noderc = require( path.relative( __dirname , process.env.NODE_RC_FILE ) );
実は上記コードでは不完全で、参照パスが同階層のディレクトリにあった場合、エラーになります。
module.js:550
throw err;
^
Error: Cannot find module 'noderc.js'
at Function.Module._resolveFilename (module.js:548:15)
at Function.Module._load (module.js:475:25)
at Module.require (module.js:597:17)
at require (internal/module.js:11:18)
at Object.<anonymous> (/mnt/c/pg/node/tmp.js:10:14)
at Module._compile (module.js:653:30)
at Object.Module._extensions..js (module.js:664:10)
at Module.load (module.js:566:32)
at tryModuleLoad (module.js:506:12)
at Function.Module._load (module.js:498:3)
なぜか。同階層に参照パスがある場合、./noderc.js
といったパスではなくnoderc.js
というパスとして値が返されます。
わかりやすく言うとこういうことですね。
var noderc = require( "noderc.js" ); # => ERROR
var noderc = require( "../node/noderc.js" ); # => OK
var noderc = require( "./noderc.js" ); # => OK
なので以下を書いてみました。パスが”noderc.js”みたいなものであるとき、”./noderc.js”へ変換するものです。
global.require_absolute = function( filepath ){
if ( ! /^\./.test( path.relative( __dirname , filepath ) ) ){
global.noderc = require( `./${ path.relative( __dirname , filepath ) }` );
} else {
global.noderc = require( path.relative( __dirname , filepath ) );
}
}
そして使用例。
require_absolute( "/mnt/c/pg/node/noderc.js" ) ;
require_absolute( process.env.NODE_RC_FILE ) ;
nodejsのrequireに関しては深い議論がされているようです。このトピックだけで2000スター。
Better local require() paths for Node.js
追記
すみません間違えてました。以下のほうが汎用性が高いです。
global.to_relative = function( filepath ){
if ( ! /^\./.test( path.relative( __dirname , filepath ) ) ){
return `./${ path.relative( __dirname , filepath ) }` ;
} else {
return path.relative( __dirname , filepath ) ;
}
}
var noderc = require( to_relative( process.env.NODE_RC_FILE ) ) ;