Как использовать пакет, установленный локально в модулях узла?

как использовать локальную версию модуля в node.js. Например, в моем приложении я установил coffee-script:

npm install coffee-script

это устанавливает его в ./node_modules и команда кофе находится в ./node_modules/.bin/coffee. Есть ли способ запустить эту команду, когда я нахожусь в основной папке моего проекта? Думаю, я ищу что-то похожее на bundle exec в упаковщик. В принципе, я хотел бы указать версию coffee-script, которую должны использовать все участники проекта.

Я знаю, что могу добавить -g флаг, чтобы установить его глобально, поэтому кофе отлично работает в любом месте, но что, если бы я хотел иметь разные версии кофе для каждого проекта?

22 ответов


проблема с вводом

./node_modules/.bin

в ваш путь является то, что он работает только тогда, когда ваш текущий рабочий каталог является корнем вашей структуры каталогов проекта (т. е. расположение node_modules)

независимо от того, что ваш рабочий каталог, вы можете получить путь локально установленных двоичных файлов с

npm bin

для выполнения локально установленного coffee двоичный независимо от того, где вы находитесь в иерархии каталогов проекта, вы можете использовать этот bash построить

PATH=$(npm bin):$PATH coffee

Я сгладил это в npm-exec

alias npm-exec='PATH=$(npm bin):$PATH'

Итак, теперь я могу

npm-exec coffee

выполнить правильную копию кофе независимо от того, где я нахожусь

$ pwd
/Users/regular/project1

$ npm-exec which coffee
/Users/regular/project1/node_modules/.bin/coffee

$ cd lib/
$ npm-exec which coffee
/Users/regular/project1/node_modules/.bin/coffee

$ cd ~/project2
$ npm-exec which coffee
/Users/regular/project2/node_modules/.bin/coffee

Nice example

вам не нужно манипулировать на $PATH или в локальных двоичных файлах проекта и выполните это.

вызов npx <command>, когда <command> уже нет $PATH автоматически установит пакет с этим именем из реестра NPM для вас и вызовет его. Когда это будет сделано, установленный пакет не будет нигде в ваших глобалах, поэтому вам не придется беспокоиться о загрязнении в долгосрочной перспективе. Вы можете предотвратить это поведение, предоставив .

на npm < 5.2.0, вы можете установить npx пакета вручную, выполнив следующую команду:

$ npm install -g npx

использовать npm bin команда для получения каталога node modules / bin вашего проекта

$ $(npm bin)/<binary-name> [args]

например

$ $(npm bin)/bower install

использовать npm run[-script] <script name>

после использования npm для установки пакета bin на локальный


использовать npm-run.

из readme:

npm-run

найти и запустить локальные исполняемые файлы из папки node_modules

любой исполняемый файл, доступный сценарию жизненного цикла npm, доступен для npm-run.

использование

$ npm install mocha # mocha installed in ./node_modules
$ npm-run mocha test/* # uses locally installed mocha executable 

установка

$ npm install -g npm-run

обновление: Я больше не рекомендую этот метод, как по упомянутым причинам безопасности, так и не в последнюю очередь более новый


решение пути имеет проблему, если $(npm bin) помещается в ваш .профиль./bashrc / etc он оценивается один раз и навсегда устанавливается в любой каталог, в котором путь был впервые оценен. Если вместо этого вы измените текущий путь, то каждый раз, когда вы запускаете скрипт, ваш путь будет расти.

чтобы обойти эти проблемы, я создаю функцию и использовал это. Он не изменяет вашу среду и прост в использовании:

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

Это можно использовать как это без внесение любых изменений в окружающую среду:

npm-exec r.js <args>

если вы хотите сохранить npm, то справку по NPX должны делать то, что вам нужно.


если переключение на пряжу (замена npm на facebook) является вариантом для вас, то вы можете позвонить:

 yarn yourCmd

скрипты внутри упаковки.JSON будет иметь приоритет, если никто не найден, он будет искать внутри .

он также выводит то, что он побежал:

$ yarn tsc
yarn tsc v0.27.5
$ "/home/philipp/rate-pipeline/node_modules/.bin/tsc"

таким образом, вам не нужно настраивать сценарии для каждой команды в вашем package.json.


если бы у вас был сценарий, определенный в .scripts внутри package.json:

"tsc": "tsc" // each command defined in the scripts will be executed from `./node_modules/.bin/` first

yarn tsc было бы эквивалентно yarn run tsc или npm run tsc:

 yarn tsc
 yarn tsc v0.27.5
 $ tsc

если вы хотите, чтобы переменная PATH правильно обновлялась на основе текущего рабочего каталога, добавьте это в конец своего .bashrc - эквивалент (или после всего, что определяет 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

Это может добавить небольшую задержку каждый раз, когда запрос bash получает визуализацию (в зависимости от размера вашего проекта, скорее всего), поэтому он отключен по умолчанию.

вы можете включить и отключить его в вашем терминале, запустив node-mode и node-mode-off, соответственно.


Я предпочитаю не полагаться на псевдонимы оболочки или другой пакет.

добавление простой строки в вашего package.json, вы можете запускать локальные команды npm, такие как

npm run webpack

.в JSON

{ "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "webpack": "webpack" }, "devDependencies": { "webpack": "^4.1.1", "webpack-cli": "^2.0.11" } }


zxc похоже на "bundle exec" для nodejs. Это похоже на использование PATH=$(npm bin):$PATH:

$ npm install -g zxc
$ npm install gulp
$ zxc which gulp
/home/nathan/code/project1/node_modules/.bin/gulp

Same @regular ' s принятое решение, но вкус раковины рыбы

if not contains (npm bin) $PATH
    set PATH (npm bin) $PATH
end

Для Windows

хранить в файле с именем npm-exec.bat и добавить его в свой %PATH%

@echo off
set cmd="npm bin"
FOR /F "tokens=*" %%i IN (' %cmd% ') DO SET modules=%%i
"%modules%"\%*

использование

затем вы можете использовать его как npm-exec <command> <arg0> <arg1> ...

для выполнения wdio установленный в локальном каталоге node_modules, выполните:

npm-exec wdio wdio.conf.js

т. е. он будет работать .\node_modules\.bin\wdio wdio.conf.js


вы также можете использовать direnv и изменить переменную $PATH только в своей рабочей папке.

$ cat .envrc
> export PATH=$(npm bin):$PATH

добавить этот скрипт в свой .bashrc. Тогда вы можете позвонить coffee или anyhting локально. Это удобно для вашего ноутбука, но не используйте его на своем сервере.

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;

Примечание: этот скрипт делает псевдоним , и после каждого вызова cd он проверяет node_modules/.bin и добавить его в свой $PATH.

примечание 2: вы можете изменить третью строку с NODE_MODULES=$(npm bin);. Но это сделало бы cd команда слишком медленная.


для Windows используйте это:

/* cmd into "node_modules" folder */
"%CD%\.bin\grunt" --version

я столкнулся с той же проблемой и мне не особо нравится использовать псевдонимы (как обычный), и если вам они тоже не нравятся, вот еще один обходной путь, который я использую, сначала вам нужно создать крошечный исполняемый скрипт bash, скажем setenv.sh:

#!/bin/sh

# Add your local node_modules bin to the path
export PATH="$(npm bin):$PATH"

# execute the rest of the command
exec "$@"

и затем вы можете использовать любые исполняемые файлы в локальной /bin С помощью этой команды:

./setenv.sh <command>
./setenv.sh 6to5-node server.js
./setenv.sh grunt

если вы используете scripts в пакет.json тогда:

...,
scripts: {
    'start': './setenv.sh <command>'
}

Я хотел бы знать, является ли это небезопасной / плохой идеей, но, подумав об этом немного, я не вижу здесь проблемы:

изменение небезопасного решения Linus, чтобы добавить его в конец, используя npm bin чтобы найти каталог и сделать скрипт только вызовом npm bin когда package.json присутствует в родительской (для скорости), это то, что я придумал для zsh:

find-up () {
  path=$(pwd)
  while [[ "$path" != "" && ! -e "$path/" ]]; 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
}

на bash, вместо precmd крючок, вы можете использовать $PROMPT_COMMAND переменная (у меня нет протестировано это, но вы получаете идею):

__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"

Я Windows user и это то, что сработало для меня:

// First set some variable - i.e. replace is with "xo"
D:\project\root> set xo="./node_modules/.bin/"

// Next, work with it
D:\project\root> %xo%/bower install

Удачи.


в случае, если вы используете fish shell и не хотите добавлять в $path по причинам безопасности. Мы можем добавить функцию ниже для запуска исполняемых файлов локального узла.

### run executables in node_module/.bin directory
function n 
  set -l npmbin (npm bin)   
  set -l argvCount (count $argv)
  switch $argvCount
    case 0
      echo please specify the local node executable as 1st argument
    case 1
      # for one argument, we can eval directly 
      eval $npmbin/$argv
    case '*'
      set --local executable $argv[1]
      # for 2 or more arguments we cannot append directly after the $npmbin/ since the fish will apply each array element after the the start string: $npmbin/arg1 $npmbin/arg2... 
      # This is just how fish interoperate array. 
      set --erase argv[1]
      eval $npmbin/$executable $argv 
  end
end

теперь вы можете запустить такую вещь, как:

n coffee

или больше аргументов типа:

n browser-sync --version

Примечание, Если вы bash пользователь, затем @Bob9630 answers-это способ использовать bash $@, который не доступен в fishshell.


Я всегда использовал тот же подход, что и @guneysus для решения этой проблемы, которая создает скрипт в пакете.JSON-файл и используйте его под управлением npm run script-name.

однако, в последние месяцы я использую справку по NPX и мне это нравится.

например, я загрузил угловой проект, и я не хотел устанавливать угловой CLI глобально. Итак, с установленным npx вместо использования глобальной угловой команды cli (если бы я ее установил), как это:

ng serve

Я могу сделать это из консоли:

npx ng serve

включить coffee-script в пакет.json с определенной версией, требуемой в каждом проекте, обычно так:

"dependencies":{
  "coffee-script": ">= 1.2.0"

затем запустите npm install для установки зависимостей в каждом проекте. Это позволит установить указанную версию coffee-скрипта, которая будет доступна локально для каждого проекта.