Как использовать пакет, установленный локально в node_modules?
Как использовать локальную версию модуля в node.js
. Например, в моем приложении я установил кофе script:
npm install coffee-script
Это устанавливает его в ./node_modules
, а команда кофе находится в ./node_modules/.bin/coffee
. Есть ли способ запустить эту команду, когда я в главной папке проекта? Наверное, я ищу что-то похожее на bundle exec
в bundler. В принципе, я хотел бы указать версию кофе script, которую должны использовать все участники проекта.
Я знаю, что могу добавить флаг -g
, чтобы установить его в глобальном масштабе, чтобы кофе работал в любом месте, но что, если бы я хотел иметь разные варианты кофе в проекте?
Ответы
Ответ 1
ОБНОВЛЕНИЕ: Как отмечает Сён Чонг в своем ответе ниже, с npm 5.2.0 вы можете использовать npx [command]
, что более удобно.
OLD ANSWER для версий до 5.2.0:
Проблема с помещением
./node_modules/.bin
в ваш PATH - это то, что он работает только тогда, когда ваш текущий рабочий каталог является корнем вашей структуры каталога проекта (т.е. местоположением node_modules
)
Независимо от вашего рабочего каталога вы можете получить путь локально установленных двоичных файлов с помощью
npm bin
Для выполнения локально установленный coffee
двоичных независимо, где вы находитесь в иерархии каталогов проекта вы можете использовать эту конструкцию Баша
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
Ответ 2
![Nice example]()
Вам больше не нужно манипулировать $PATH
!
Начиная с [email protected], npm поставляется с пакетом npx
, который позволяет запускать команды из локального node_modules/.bin
или из центрального кеша.
Просто запустите:
$ npx [options] <command>[@version] [command-arg]...
По умолчанию npx
будет проверять наличие <command>
в $PATH
или в локальных бинарниках проекта и выполнить это.
Вызов npx <command>
когда <command>
еще не находится в вашем $PATH
, автоматически установит пакет с этим именем из реестра NPM для вас и вызовет его. Когда это будет сделано, установленный пакет не будет нигде в вашем мире, поэтому вам не придется беспокоиться о загрязнении в долгосрочной перспективе. Это можно предотвратить, --no-install
параметр --no-install
.
Для npm < 5.2.0
вы можете установить пакет npx
вручную, выполнив следующую команду:
$ npm install -g npx
Ответ 3
Используйте команду npm bin
, чтобы получить каталог node modules/bin вашего проекта
$ $(npm bin)/<binary-name> [args]
например.
$ $(npm bin)/bower install
Ответ 4
Использовать npm run[-script] <script name>
После использования npm для установки пакета bin в локальный каталог ./node_modules
, измените package.json
чтобы добавить <script name>
следующим образом:
$ npm install --save learnyounode
$ edit packages.json
>>> in packages.json
...
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"learnyounode": "learnyounode"
},
...
$ npm run learnyounode
Было бы неплохо, если бы в npm install была опция -add -script или что-то в этом роде, или если npm run работал без добавления в блок сценариев.
Ответ 5
Используйте npm-run
.
Из файла readme:
NPM перспективе
Найти и запустить локальные исполняемые файлы из node_modules
Любой исполняемый файл, доступный для жизненного цикла npm script, доступен для npm-run
.
Использование
$ npm install mocha # mocha installed in ./node_modules
$ npm-run mocha test/* # uses locally installed mocha executable
Установка
$ npm install -g npm-run
Ответ 6
Обновление: Я больше не рекомендую этот метод, как по указанным причинам безопасности, так и по крайней мере более новой команде npm bin
. Оригинальный ответ ниже:
Как вы узнали, любые локально установленные двоичные файлы находятся в ./node_modules/.bin
. Чтобы всегда запускать двоичные файлы в этом каталоге, а не в глобально доступных двоичных файлах, если они присутствуют, я предлагаю вам сначала положить ./node_modules/.bin
в свой путь:
export PATH="./node_modules/.bin:$PATH"
Если вы поместите это в свой ~/.profile
, coffee
всегда будет ./node_modules/.bin/coffee
, если он доступен, в противном случае /usr/local/bin/coffee
(или любой другой префикс, который вы устанавливаете под модулями node).
Ответ 7
Решение PATH имеет проблему: если $(npm bin) помещается в ваш .profile/.bashrc/etc, он оценивается один раз и навсегда устанавливается в зависимости от того, какой каталог был сначала оценен. Если вместо этого вы изменяете текущий путь, то каждый раз, когда вы запускаете script, ваш путь будет расти.
Чтобы обойти эти проблемы, я создаю функцию и использую ее. Он не изменяет вашу среду и прост в использовании:
function npm-exec {
$(npm bin)/[email protected]
}
Затем это можно использовать таким образом, не внося никаких изменений в вашу среду:
npm-exec r.js <args>
Ответ 8
Если вы хотите сохранить npm, тогда npx должен делать то, что вам нужно.
Если переключение на пряжу (замена npm на facebook) является для вас вариантом, вы можете позвонить:
yarn yourCmd
скрипты внутри package.json будут иметь приоритет, если ни один не найден, он ./node_modules/.bin/
папку ./node_modules/.bin/
.
Он также выводит то, что он запускал:
$ yarn tsc
yarn tsc v0.27.5
$ "/home/philipp/rate-pipeline/node_modules/.bin/tsc"
Поэтому вам не нужно настраивать скрипты для каждой команды в вашем package.json
. 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
Ответ 9
Если вы хотите, чтобы ваша переменная 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
соответственно.
Ответ 10
Я предпочитаю не полагаться на псевдонимы оболочки или другой пакет.
Добавив простую строку в раздел scripts
вашего package.json
, вы можете запускать локальные команды npm, такие как
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"
}
}
Ответ 11
Я всегда использовал тот же подход, что и @guneysus, чтобы решить эту проблему: создать скрипт в файле package.json и использовать его, запустив npm run script-name.
Тем не менее, в последние месяцы я использую NPX, и мне это нравится.
Например, я скачал проект Angular и не хотел устанавливать Angular CLI глобально. Итак, с установленным npx, вместо использования глобальной угловой команды cli (если я ее установил), вот так:
ng serve
Я могу сделать это из консоли:
npx ng serve
Вот статья, которую я написал о NPX, и это еще глубже.
Ответ 12
То же самое, что и принято, но вкус рыбной раковины
if not contains (npm bin) $PATH
set PATH (npm bin) $PATH
end
Ответ 13
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
Ответ 14
обновление: если вы на недавнем npm (версия> 5.2)
Ты можешь использовать:
npx <command>
npx
ищет команду в каталоге .bin
если ваш node_modules
старый ответ:
Для 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
Ответ 15
Я столкнулся с той же проблемой, и мне не особенно нравится использовать псевдонимы (как предлагалось regular), и если вам это тоже не нравятся, то здесь другое обходное решение, которое я использую, сначала нужно создать крошечный исполняемый файл bash script, скажем 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 "[email protected]"
а затем вы можете использовать любые исполняемые файлы в локальном /bin
с помощью этой команды:
./setenv.sh <command>
./setenv.sh 6to5-node server.js
./setenv.sh grunt
Если вы используете scripts
в package.json, тогда:
...,
scripts: {
'start': './setenv.sh <command>'
}
Ответ 16
Мне бы хотелось узнать, является ли это небезопасной/плохой идеей, но, немного подумав об этом, я не вижу здесь проблемы:
Изменение небезопасного решения Linus, чтобы добавить его в конец, используя npm bin
, чтобы найти каталог и сделать script только вызов npm bin
, когда package.json
присутствует в родительском (для скорости), это это то, что я придумал для 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
}
Для bash
вместо использования precmd
hook вы можете использовать переменную $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"
Ответ 17
Вы также можете использовать direnv и изменить переменную $PATH только в своей рабочей папке.
$ cat .envrc
> export PATH=$(npm bin):$PATH
Ответ 18
Добавьте этот script к вашему .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 "[email protected]";
add_local_node_modules_to_path;
}
add_local_node_modules_to_path;
note: этот script выполняет команду aliase cd
, и после каждого вызова cd
он проверяет node_modules/.bin
и добавляет его в ваш $PATH
.
note2: вы можете изменить третью строку на NODE_MODULES=$(npm bin);
. Но это сделало бы команду cd
слишком медленной.
Ответ 19
Я пользователь 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
Удачи.
Ответ 20
Для Windows используйте это:
/* cmd into "node_modules" folder */
"%CD%\.bin\grunt" --version
Ответ 21
Если вы используете fish shell
и не хотите добавлять к $path
по соображениям безопасности. Мы можем добавить следующую функцию для запуска локальных исполняемых файлов node.
### 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 [email protected]
, который недоступен в fishshell
.
Ответ 22
Включите coffee- script в package.json с конкретной версией, требуемой в каждом проекте, как правило:
"dependencies":{
"coffee-script": ">= 1.2.0"
Затем запустите npm install для установки зависимостей в каждом проекте. Это установит указанную версию coffee- script, которая будет доступна локально для каждого проекта.