Determining Node modules location at runtime

2019-06-05 00:36发布

问题:

I am building a tool which is basically a node.js module. This tool can be installed globally (with -g option) I have few static files in the module to generate a report. If the module is invoked locally, I can refer to the static files with relative path ./node_modules/<module>/static/filename. But when the tool is invoked as a command, how do I refer to the static files? And how can I determine whether the tool is invoked as a local module or as a command?

回答1:

Use the magic variable __dirname. It refers to the directory containing your script file.

http://nodejs.org/api/globals.html#globals_dirname



回答2:

When your tool is installed globally, there are usually two entries on Unix systems:

  • /usr/local/lib/node_modules/<module>/ -> the directory containing all module source files
  • /usr/local/bin/<script.js> -> symlink to your module executable script

Because Node is using the real path (i.e. after all symlinks were resolved) to resolve a path relative to current module, you don't need to worry about differences between global and local install.

What you do need to handle is the possibly different current working directory where the node process is running. The solution is to resolve the relative path to your static file against the absolute path where your module resides, not to assume that the node process will run in a particular directory as you do in your example.

There are two ways for that:

  1. Using __dirname (API docs), which contains the directory name (path) of the current source file:

    var path = require('path');
    // assuming this script is in package root directory
    var staticFile = path.resolve(__dirname, 'static', 'filename');
    // if the script is in lib/ subdirectory, then you want to call
    var staticFile = path.resolve(__dirname, '..', 'static', 'filename');
    
  2. Using require.resolve(), which returns the exact same filename as would be used by a call to require():

    // assuming this script is in package root directory
    var staticFile = require.resolve('./static/filename');
    // if the script is in lib/ subdirectory, then you want to call
    var staticFile = require.resolve('../static/filename');