node.JSでは、requireを介してロードしたモジュールのパスを取得するにはどうすればよいですか(つまり、一部のnode_moduleにあります)


93

npm経由でインストールされたモジュールが必要です。そのモジュールの下位にある.jsファイルにアクセスしたい(そのため、コンストラクターメソッドをサブクラス化できる)。モジュールのコードを変更することはできません(まあ、したくありません)。そのため、__ dirnameを抽出する場所がありません。

私は次の質問を知っていますが、コード制御できるモジュールのパスを取得することについてです(したがって、__ dirnameが解決策です): Node.jsでは、どのように `this`モジュールのパスを確認できますか?

~~~

さらに良いのは、モジュールのロードされたモジュール情報を取得することです


require( 'modulename')でエラーなしにモジュールをロードできる場所はどこですか?
フューチャー

もっとよく説明できますか?いくつかのコード?
ガブリエルラマ

回答:


127

私があなたの質問を正しく理解している場合は、require.resolve()を使用する必要があります:

内部require()機構を使用してモジュールの場所を検索しますが、モジュールをロードするのではなく、解決されたファイル名を返します。

例: var pathToModule = require.resolve('module');


13
この回答は、すべてのノードモジュールで確実に機能するわけではありません。私の答えを見てください。
Jason

57

require.resolve()は部分的な答えです。受け入れられた回答は多くのノードモジュールで機能する可能性がありますが、すべてでは機能しません。

require.resolve("moduleName")モジュールがインストールされているディレクトリは表示されません。mainモジュールのの属性で定義されているファイルの場所を示しますpackage.json

そうかもしれないしmoduleName/index.js、そうかもしれないmoduleName/lib/moduleName.js。後者の場合、path.dirname(require.resolve("moduleName"))不要または予期しないディレクトリが返されます。node_modules/moduleName/lib

特定のモジュールへの完全なパスを取得する正しい方法は、ファイル名を解決することです。

let readmePath = require.resolve("moduleName/README.md");

モジュールのディレクトリだけが必要な場合は(多くのpath.join()呼び出しを行う可能性があります)、次に解決しますpackage.json -を -これは常にプロジェクトのルートにある必要があります-に渡してpath.dirname()

let packagePath = path.dirname(require.resolve("moduleName/package.json"));

1
package.jsonファイルを検出することにより、非常に巧妙な答え。あなたはpath.join('moduleName', 'package.json')Windows互換であるために使うべきではありませんか?
ジョアンピメンテルフェレイラ

2
@JoãoPimentelFerreira require.resolveはプラットフォームに依存しrequireないため、使用する必要はありませんpath.join
Gopikrishna S

1
const path = require('path');を使用する前に、必ず追加してくださいpath.dirname
GOTO 0

この答えが完全に真実であることを望みます!私は正常のように何か解決することができますrequire.resolve('@scope/module')私のような何かを与えるが/path/to/@scope/module/dist/index.js、私が実行しようとただした場合、require.resolve('@scope/module/package.json')それはスローMODULE_NOT_FOUNDエラーを。私はノード14.4.0にいて、解決しようとしているモジュールの"type": "module"package.jsonに、exportsを含まないフィールドがありますpackage.json。それが何かと関係があるかどうか
わかり

私は問題を発見しました:モジュールにがあるtype: module場合、明らかpackage.jsonexportsフィールドで明示的に公開する必要があります。Nodeの新しいESM機能はrequire通常のようにパスの解決を妨げるものではないと考えましたが、明らかにそうです。
trusktr

3

参考までrequire.resolveに、CommonJSに従ってモジュール識別子を返します。node.jsでは、これはファイル名です。WebPACKこれは数です。

WebPACKの状況、ここに私の解決策は、モジュールのパスを見つけることです。

const pathToModule = require.resolve('module/to/require');
console.log('pathToModule is', pathToModule); // a number, eg. 8
console.log('__webpack_modules__[pathToModule] is', __webpack_modules__[pathToModule]);

それから__webpack_modules__[pathToModule]私はこのような情報を得ました:

(function(module, exports, __webpack_require__) {

    eval("module.exports = (__webpack_require__(6))(85);\n\n//////////////////\n// 
    WEBPACK FOOTER\n// delegated ./node_modules/echarts/lib/echarts.js from dll-reference vendor_da75d351571a5de37e2e\n// module id = 8\n// module chunks = 0\n\n//# sourceURL=webpack:///delegated_./node_modules/echarts/lib/echarts.js_from_dll-reference_vendor_da75d351571a5de37e2e?");

    /***/
})

以前のdllビルドファイルの古いスクリプトが必要なため(ビルド速度を上げるため)、更新したモジュールファイルが期待どおりに機能しませんでした。最後に、dllファイルを再構築して、問題を解決しました。

参照:を使用require.resolveして解決済みファイルパス(ノード)を取得する


2

私はあなたのニーズを正しく理解できれば幸いです:いくつかのモジュールのエントリポイントファイルを取得します。jugglingdbモジュールのエントリポイントを取得するとします。

node
> require('module')._resolveFilename('jugglingdb')
'/usr/local/lib/node_modules/jugglingdb/index.js'

ご覧のとおり、これはモジュールに関するこの種の情報を取得するための「公式な」方法ではないため、この関数の動作はバージョンによって異なる場合があります。ノードソースで見つけました:https : //github.com/joyent/node/blob/master/lib/module.js#L280


2

@anatoliyソリューションによると、MacOS XIではルックアップパスが

require('module')._resolveLookupPaths('myModule')

解決されたルックアップパスを取得します

[ 'myModule',
  [ '/Users/admin/.node_modules',
    '/Users/admin/.node_libraries',
    '/usr/local/lib/node' ] ]

一方

require('module')._resolveFilename('myModule')

とにかく私が探していたモジュールを解決しません、実際、クレイジーなことは_load、モジュールが解決しないことです:

> require('module')._load('myModule')
Error: Cannot find module 'myModule'
    at Function.Module._resolveFilename (module.js:440:15)
    at Function.Module._load (module.js:388:25)
    at repl:1:19
    at sigintHandlersWrap (vm.js:32:31)
    at sigintHandlersWrap (vm.js:96:12)
    at ContextifyScript.Script.runInContext (vm.js:31:12)
    at REPLServer.defaultEval (repl.js:308:29)
    at bound (domain.js:280:14)
    at REPLServer.runBound [as eval] (domain.js:293:12)
    at REPLServer.<anonymous> (repl.js:489:10)

しばらくrequireは以下となります。

> require('myModule')

しかし、私はこのモジュールを持っていません

myProject/node_modules/
myProject/node_modules/@scope/
/usr/local/lib/node_modules/
/usr/local/lib/node_modules/@scope
/usr/local/lib/node_modules/npm/node_modules/
/usr/local/lib/node_modules/npm/node_modules/@scope
$HOME/.npm/
$HOME/.npm/@scope/

このモジュールはどこにあるのですか?

まず、私がしなければならなかった$ sudo /usr/libexec/locate.updatedb 私は、いくつかのコーヒーの後に続いてlocate myModuleまたはより良いですlocate myModule/someFile.js

ちなみに、それは私のプロジェクトの親フォルダー、つまり私のプロジェクトルートフォルダーの外にあったことがわかります。

$pwd
/Users/admin/Projects/Node/myProject
$ ls ../../node_modules/myModule/

ですからrm -rf ../../node_modules/myModule/、新鮮なものは避けられませんnpm install

npmコンピューターをスキャンして、実行するはずのプロジェクトルートフォルダーまたはデフォルトのモジュール検索パス以外の場所でモジュールを検索するように指示された人はいないと私は主張できます。


1

これはおそらくあなたが探しているものです、チェックしてください:

require.main.filename


1

Node.js ESMとexportsフィールドが登場するまで、Jasonの答えが最良の答えでした。

Nodeは、パッケージの作成者が明示的にそれらを公開することを決定しない限り、exportsデフォルトでファイルをpackage.json解決できないようにするフィールドを持つパッケージをサポートするようになったため、Jasonの答えのトリックは、明示的に公開しないパッケージでは失敗しますpackage.json

resolve-package-pathトリックを実行するというパッケージがあります。

使用方法は次のとおりです。

const resolvePkg = require('resolve-package-path')

console.log(resolvePkg('@some/package'))

これは次のようなものを出力します

/path/to/@some/package/package.json

パッケージのexportsフィールドに何が含まれているかに関係なく。


著者がモジュールのコンテンツの一部を意識的にエクスポートすると、あなたはさらに不安定な状況に陥ったのではないかと思います。それは、明示的にエクスポートされないもののより積極的なリファクタリングをもたらす傾向があると思いますか?
Jason

@Jasonソースファイルについても同様ですが、package.jsonファイルはなくなりません。インポートから非表示にする必要がある理由はわかりません。
trusktr
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.