node.JS에서 내가로드 한 모듈의 경로를 어떻게 얻을 수 있습니까? (예 : 일부 node_module에서)


94

npm을 통해 설치된 모듈이 필요합니다. 해당 모듈에 종속 된 .js 파일에 액세스하고 싶습니다 (그래서 생성자 메서드를 하위 클래스로 만들 수 있습니다). 모듈의 코드를 수정할 수 없으므로 (글쎄요, 원하지 않습니다) __dirname을 추출 할 장소가 없습니다.

다음 질문을 알고 있지만 코드 제어 권한이있는 모듈의 경로를 얻는 것입니다 (따라서 __dirname이 해결책입니다). Node.js에서`this` 모듈의 경로를 어떻게 알 수 있습니까?

~~~

모듈의로드 된 모듈 정보를 얻는 것이 더 좋습니다.


require ( 'modulename')로 오류없이 모듈을로드 할 수있는 곳은 어디입니까?
Futur 2011-04-11

더 잘 설명 할 수 있습니까? 일부 코드?
Gabriel Llamas

답변:


130

질문을 올바르게 이해했다면 require.resolve () 를 사용해야합니다 .

내부 require () 기계를 사용하여 모듈의 위치를 ​​찾되 모듈을로드하는 대신 확인 된 파일 이름을 반환하십시오.

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


13
이 답변은 모든 노드 모듈에서 안정적으로 작동하지 않습니다. 내 대답을 참조하십시오.
제이슨

61

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 호환을 위해 사용하지 않아야 합니까?
João Pimentel Ferreira

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오류가 발생합니다. 저는 Node 14.4.0에 있으며 해결하려는 모듈은 .NET Framework를 포함하지 않는 필드가 "type": "module"있는 package.json에 exports있습니다 package.json. 그것과 관련이 있는지 확실하지 않습니다 ...
trusktr

나는 문제를 발견했다 : 모듈 이을 가지고있을 때 type: module, 분명히 필드에 package.json명시 적으로 노출되어야한다 exports. Node의 새로운 ESM 기능이 require평소처럼 경로를 해결하는 것을 차단하지 않는다고 생각 했지만 분명히 그렇습니다.
trusktr

3

참고 require.resolve로 CommonJS에 따라 모듈 식별자를 반환합니다. node.js에서 이것은 파일 이름입니다. 에서 웹팩 이 숫자입니다.

에서 웹팩 상황, 여기에 모듈 경로를 알아 내 솔루션입니다 :

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

et voilà, 그것은 내 프로젝트의 상위 폴더, 즉 내 프로젝트 루트 폴더 외부에 있음을 알 수 있습니다.

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

그래서 당신은 피할 수없고 rm -rf ../../node_modules/myModule/신선한 npm install.

npm실행해야 할 프로젝트 루트 폴더 또는 기본 모듈 검색 경로가 아닌 다른 모듈을 검색 할 때 컴퓨터를 스캔 하도록 지시 한 사람은 아무도 없다고 주장 할 수 있습니다 .


1

이것은 아마도 당신이 찾고있는 것일 수 있습니다.

require.main.filename


1

Jason의 대답은 Node.js ESM과 exports필드가 나올 때까지 최고의 대답이었습니다 .

이제 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.