Как использовать пакет, установленный локально в узловых модулях?
как использовать локальную версию модуля в 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
вы не должны манипулировать на
$PATH
, или в локальных двоичных файлах проекта, и выполните это.вызов
npx <command>
, когда<command>
уже нет$PATH
автоматически установит пакет с этим именем из реестра NPM для вас и вызовет его. Когда это будет сделано, установленный пакет не будет нигде в ваших глобалах, поэтому вам не придется беспокоиться о загрязнении в долгосрочной перспективе. Вы можете предотвратить такое поведение, предоставив .на
npm < 5.2.0
, вы можете установитьnpx
пакета вручную, выполнив следующую команду:$ npm install -g npx
использовать
npm bin
команда для получения каталога модулей узлов / 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>
если вы хотите сохранить НПМ, затем npx должны делать то, что вам нужно.
если переключение на yarn (замена 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
если вы хотите, чтобы ваша переменная пути правильно обновлялась на основе вашего текущего рабочего каталога, добавьте это в конец вашего
.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
такое же @регулярн принятое решение, но вкус раковины Рыб
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
или во всяком случае локально. Это удобно для вашего ноутбука, но не используйте его на своем сервере.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
команда слишком медленная.
я столкнулся с той же проблемой и мне не особо нравится использовать псевдонимы (как обычныйпредлагается), и если вам они тоже не нравятся, то вот еще один обходной путь, который я использую, вам сначала нужно создать крошечный исполняемый скрипт 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>' }
Я хотел бы знать, если это небезопасно/плохая идея, но подумав немного, я не вижу здесь проблемы:
изменение небезопасного решения Линуса, чтобы добавить его в конец, используя
npm bin
чтобы найти каталог, и сделать скрипт только вызовnpm bin
когда apackage.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
пользователей и это то, что сработало для меня:// 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 ответы-это способ пойти, используя bash's$@
, который не доступен вfishshell
.
Я всегда использовал тот же подход, что и @guneysus для решения этой проблемы, которая заключается в создании скрипта в пакете.JSON-файл и использовать его под управлением npm run script-name.
однако, в последние месяцы я использую npx и мне это нравится.
например, я загрузил угловой проект, и я не хотел устанавливать угловой CLI глобально. Итак, с установленным npx вместо использования команды global angular cli (если бы я ее установил), например это:
ng serve
Я могу сделать это из консоли:
npx ng serve
включить кофе-скрипт в пакет.json с конкретной версией, необходимой в каждом проекте, как правило, так:
"dependencies":{ "coffee-script": ">= 1.2.0"
затем запустите npm install для установки зависимостей в каждом проекте. Это позволит установить указанную версию coffee-script, которая будет доступна локально для каждого проекта.