In node.JS how can I get the path of a module I have loaded via require that is *not* mine (i.e. in some node_module)

前端 未结 7 1630
清歌不尽
清歌不尽 2020-12-02 15:16

I require a module that was installed via npm. I want to access a .js file subordinate to that module (so I can subclass a Constructor method in it). I can\'t (well, don\'t

相关标签:
7条回答
  • 2020-12-02 15:31

    This is maybe what you're looking for, check:

    require.main.filename

    0 讨论(0)
  • 2020-12-02 15:32

    require.resolve() is a partial answer. The accepted answer may work for many node modules, but won't work for all of them.

    require.resolve("moduleName") doesn't give you the directory where the module is installed; it gives you the location of the file defined in the main attribute in the module's package.json.

    That might be moduleName/index.js or it could be moduleName/lib/moduleName.js. In the latter case, path.dirname(require.resolve("moduleName")) will return a directory you may not want or expect: node_modules/moduleName/lib

    The correct way to get the complete path to a specific module is by resolving the filename:

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

    If you just want the directory for the module (maybe you're going to make a lot of path.join() calls), then resolve the package.json — which must always be in the root of the project — and pass to path.dirname():

    let packagePath = path.dirname(require.resolve("moduleName/package.json"));
    
    0 讨论(0)
  • 2020-12-02 15:39

    FYI, require.resolve returns the module identifier according to CommonJS. In node.js this is the filename. In webpack this is a number.

    In webpack situation, here is my solution to find out the module path:

    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]);
    

    Then from __webpack_modules__[pathToModule] I got information like this:

    (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?");
    
        /***/
    })
    

    Turned out I required old scripts from previous dll build file(for faster build speed), so that my updated module file didn't work as I expected. Finally I rebuilt my dll file and solved my problem.

    Ref: Using require.resolve to get resolved file path (node)

    0 讨论(0)
  • 2020-12-02 15:41

    I hope I correctly understand your needs: to get entry point file of some module. Let's say you want to get entry point of jugglingdb module:

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

    As you can see this is not "official" way to get this kind of information about module, so behavior of this function may change from version to version. I've found it in node source: https://github.com/joyent/node/blob/master/lib/module.js#L280

    0 讨论(0)
  • 2020-12-02 15:45

    According to @anatoliy solution, On MacOS X I have found the lookup paths doing

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

    so I get the resolved lookup paths

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

    whereas the

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

    will not resolve the module I was looking for anyways, in fact the crazy thing is that the _load will not resolve the module:

    > 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)
    

    while the require will:

    > require('myModule')
    

    but I don't have this module in

    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/
    

    so where is this module???

    First I had to do a $ sudo /usr/libexec/locate.updatedb Then after some coffee I did locate myModule or better locate myModule/someFile.js

    et voilà, it comes out that it was in a parent folder of my project i.e. outside my project root folder:

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

    so you cannot avoid to rm -rf ../../node_modules/myModule/ and a fresh npm install.

    I can argue that no one instructed npm to scan my computer in search for modules elsewhere than my project root folder where it was supposed to run or in the default modules search path.

    0 讨论(0)
  • 2020-12-02 15:48

    Jason's answer was the best answer, until Node.js ESM and the exports field came out.

    Now that Node supports packages with an exports field that by default will prevent files like package.json from being resolvable unless the package author explicitly decides to expose them, the trick in Jason's answer will fail for packages that do not explicitly expose package.json.

    There is a package called resolve-package-path that does the trick.

    Here's how to use it:

    const resolvePkg = require('resolve-package-path')
    
    console.log(resolvePkg('@some/package'))
    

    which will output something like

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

    regardless of what the package's exports field contains.

    0 讨论(0)
提交回复
热议问题