How to use executables from a package installed locally in node_modules?

前端 未结 22 1918
时光说笑
时光说笑 2020-11-22 12:40

How do I use a local version of a module in node.js. For example, in my app, I installed coffee-script:

npm install coffee-script
相关标签:
22条回答
  • 2020-11-22 13:03

    Use npm run[-script] <script name>

    After using npm to install the bin package to your local ./node_modules directory, modify package.json to add <script name> like this:

    $ npm install --save learnyounode
    $ edit packages.json
    >>> in packages.json
    ...
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "learnyounode": "learnyounode"
    },
    ...
    $ npm run learnyounode
    

    It would be nice if npm install had a --add-script option or something or if npm run would work without adding to the scripts block.

    0 讨论(0)
  • 2020-11-22 13:04

    Add this script to your .bashrc. Then you can call coffee or anyhting locally. This is handy for your laptop, but don't use it on your server.

    DEFAULT_PATH=$PATH;
    
    add_local_node_modules_to_path(){
      NODE_MODULES='./node_modules/.bin';
      if [ -d $NODE_MODULES ]; then
        PATH=$DEFAULT_PATH:$NODE_MODULES;
      else
        PATH=$DEFAULT_PATH;
      fi
    }
    
    cd () {
      builtin cd "$@";
      add_local_node_modules_to_path;
    }
    
    add_local_node_modules_to_path;
    

    note: this script makes aliase of cd command, and after each call of cd it checks node_modules/.bin and add it to your $PATH.

    note2: you can change the third line to NODE_MODULES=$(npm bin);. But that would make cd command too slow.

    0 讨论(0)
  • 2020-11-22 13:05

    I prefer to not rely on shell aliases or another package.

    Adding a simple line to scripts section of your package.json, you can run local npm commands like

    npm run webpack

    package.json

    {
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "webpack": "webpack"
      },
      "devDependencies": {
        "webpack": "^4.1.1",
        "webpack-cli": "^2.0.11"
      }
    }
    
    0 讨论(0)
  • 2020-11-22 13:05

    If you want your PATH variable to correctly update based on your current working directory, add this to the end of your .bashrc-equivalent (or after anything that defines PATH):

    __OLD_PATH=$PATH
    function updatePATHForNPM() {
      export PATH=$(npm bin):$__OLD_PATH
    }
    
    function node-mode() {
      PROMPT_COMMAND=updatePATHForNPM
    }
    
    function node-mode-off() {
      unset PROMPT_COMMAND
      PATH=$__OLD_PATH
    }
    
    # Uncomment to enable node-mode by default:
    # node-mode
    

    This may add a short delay every time the bash prompt gets rendered (depending on the size of your project, most likely), so it's disabled by default.

    You can enable and disable it within your terminal by running node-mode and node-mode-off, respectively.

    0 讨论(0)
  • 2020-11-22 13:06

    I'd love to know if this is an insecure/bad idea, but after thinking about it a bit I don't see an issue here:

    Modifying Linus's insecure solution to add it to the end, using npm bin to find the directory, and making the script only call npm bin when a package.json is present in a parent (for speed), this is what I came up with for zsh:

    find-up () {
      path=$(pwd)
      while [[ "$path" != "" && ! -e "$path/$1" ]]; do
        path=${path%/*}
      done
      echo "$path"
    }
    
    precmd() {
      if [ "$(find-up package.json)" != "" ]; then
        new_bin=$(npm bin)
        if [ "$NODE_MODULES_PATH" != "$new_bin" ]; then
          export PATH=${PATH%:$NODE_MODULES_PATH}:$new_bin
          export NODE_MODULES_PATH=$new_bin
        fi
      else
        if [ "$NODE_MODULES_PATH" != "" ]; then
          export PATH=${PATH%:$NODE_MODULES_PATH}
          export NODE_MODULES_PATH=""
        fi
      fi
    }
    

    For bash, instead of using the precmd hook, you can use the $PROMPT_COMMAND variable (I haven't tested this but you get the idea):

    __add-node-to-path() {
      if [ "$(find-up package.json)" != "" ]; then
        new_bin=$(npm bin)
        if [ "$NODE_MODULES_PATH" != "$new_bin" ]; then
          export PATH=${PATH%:$NODE_MODULES_PATH}:$new_bin
          export NODE_MODULES_PATH=$new_bin
        fi
      else
        if [ "$NODE_MODULES_PATH" != "" ]; then
          export PATH=${PATH%:$NODE_MODULES_PATH}
          export NODE_MODULES_PATH=""
        fi
      fi   
    }
    
    export PROMPT_COMMAND="__add-node-to-path"
    
    0 讨论(0)
  • 2020-11-22 13:10

    The PATH solution has the issue that if $(npm bin) is placed in your .profile/.bashrc/etc it is evaluated once and is forever set to whichever directory the path was first evaluated in. If instead you modify the current path then every time you run the script your path will grow.

    To get around these issues, I create a function and used that. It doesn't modify your environment and is simple to use:

    function npm-exec {
       $(npm bin)/$@  
    }
    

    This can then be used like this without making any changes to your environment:

    npm-exec r.js <args>
    
    0 讨论(0)
提交回复
热议问题