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("絶対パス") とすると呼び出すことができます
ほとんどやることはないと思いますが、使用しているライブラリが独自拡張している場合に遭遇することはありえます。
- resolve-from中で登場します。
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を投げてあげましょう。