Skip to main content

NodeJSのrequireがどのファイルを探索しているのかを調べる

requireしたモジュールがどこを参照しているのかを把握する

たとえば、require("eslint")がどこに保存されているeslintを探しているのか表示する方法は、 シェルでNodeを立ち上げると

$ node
> require.resolve("eslint");
'/project/node_modules/eslint/lib/api.js'

と出力されます。これは成功する例ですが、nodeが探索する範囲にeslintがインストールされていない場合は次のようなエラーを吐きます。

$ node
> require.resolve("eslint")
{ Error: Cannot find module 'eslint'
at Function.Module._resolveFilename (internal/modules/cjs/loader.js:582:15)
at Function.resolve (internal/modules/cjs/helpers.js:30:19) code: 'MODULE_NOT_FOUND' }

requireが探索するnode_modulesの順序

原因の究明をする場合に利用します。

require.resolve.paths

$ node
> require.resolve.paths("eslint")
[ '/workspace/project/repl/node_modules',
'/workspace/project/node_modules',
'/workspace/node_modules',
'/node_modules',
'/workspace/project/.node_modules',
'/workspace/project/.node_libraries',
'/workspace/project/.nodebrew/node/v10.15.3/lib/node',
'/workspace/project/.node_modules',
'/workspace/project/.node_libraries',
'/workspace/project/.nodebrew/node/v10.15.3/lib/node' ]

_nodeModulePaths

エラーログでよく見るメソッドなので、一度叩いて挙動を確かめておくのも良いでしょう。

$ node
> const Module = require("module");
> Module._nodeModulePaths(process.cwd());
[ '/workspace/project/my-package/nest-package/node_modules',
'/workspace/project/my-package/node_modules',
'/workspace/project/node_modules',
'/workspace/node_modules',
'/node_modules' ]

現在位置から探索できるモジュール以外のモジュールを呼び出す

たとえば次のようなディレクトリ構成の場合

.
├── another
│ └ "@here"
└── himenon.github.io
└── node_modules
└── @custom-site
└── cli
└── lib
└── index.js

@hereの位置himenon.github.io/node_modulesにあるパッケージを参照してみます。

// process.cwd() <-- '/workspace/another

const path = require("path");
const Module = require("module");
const moduleName = "@custom-site/cli";
const extNodeModulePath = path.resolve(process.cwd(), "../himenon.github.io/node_modules");
const filename = path.normalize(path.join(extNodeModulePath || "", moduleName));

Module._resolveFilename(moduleName, {
id: filename,
filename: filename,
paths: [extNodeModulePath],
});
// 結果
// '/workspace/himenon.github.io/node_modules/@custom-site/cli/lib/index.js'
// 得られた結果を require("絶対パス") とすると呼び出すことができます

ほとんどやることはないと思いますが、使用しているライブラリが独自拡張している場合に遭遇することはありえます。

moduleが見つからない場合

moduleが見つからない場合の対処方法を紹介します。

対象のモジュールのpackage.jsonに"main"が設定されていることを確認する

{
"main": "index.js"
}

などの表記がない場合はエラーになります。

node_modulesを消してインストールし直す

node_modulesの容量が大きくない場合に即解決するでしょう。

rm -rf node_modules
# yarn
yarn install
# npm
npm install

git cloneし直す

できる場合はやるとよいかもしれません。 ただし、作業中のブランチがあるような場合は気をつけてください。

yarn check

yarn.lockとローカルにインストールされたパッケージのバージョン整合性を確かめましょう。 そこそこ時間がかかるので、node_modulesごと消したほうが早い場合もあります。

yarn check

cacheを消す

npm cache clean
npm i

もしくは

yarn cache clean
yarn install

パッケージ側のexports漏れ

exportsしていない場合は同頑張ってもrequireできません。

パッケージに梱包されていない

package.jsonにfilesのプロパティがあります。ここにはパッケージとして同封するファイルを記述します。 ここに記載のないものはインストール時にはダウンロードされません。 たまにOSSとかであるのでPRを投げてあげましょう。

参考