Comment utiliser un paquet installé localement dans les modules de noeuds?
comment utiliser une version locale d'un module dans node.js
. Par exemple, dans mon application, j'ai installé coffee-script:
npm install coffee-script
cela l'installe dans ./node_modules
et la commande café est dans ./node_modules/.bin/coffee
. Y a-t-il un moyen d'exécuter cette commande lorsque je suis dans le dossier principal de mon projet? Je suppose que je cherche quelque chose de similaire à bundle exec
dans bundler. Fondamentalement, je voudrais spécifier une version de café-script que tout le monde impliqué dans le projet devrait utiliser.
je sais que je peux ajouter le drapeau -g
pour l'installer globalement pour que le café fonctionne bien n'importe où, mais que faire si je voulais avoir différentes versions de café par projet?
22 réponses
Le problème avec la mise en
./node_modules/.bin
dans votre chemin est qu'il ne fonctionne que lorsque votre répertoire de travail actuel est la racine de votre structure de répertoire de projet (i.e. l'emplacement de node_modules
)
indépendamment de ce qu'est votre répertoire de travail, vous pouvez obtenir le chemin des binaires installés localement avec
npm bin
pour exécuter un binaire coffee
installé localement indépendamment de l'endroit où vous êtes dans le vous pouvez utiliser cette construction bash
PATH=$(npm bin):$PATH coffee
j'ai un alias de ce npm-exec
alias npm-exec='PATH=$(npm bin):$PATH'
donc, maintenant je peux
npm-exec coffee
pour exécuter la copie correcte de café n'importe où je suis
$ 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
plus besoin de manipuler $PATH
!
à Partir de npm@5.2.0 , mnp livré avec npx
package qui vous permet d'exécuter des commandes à partir d'un local node_modules/.bin
ou à partir d'un centre de cache.
simplement exécuter:
$ npx [options] <command>[@version] [command-arg]...
par défaut, npx
vérifiera si <command>
existe dans $PATH
, ou dans les binaires du projet local, et exécuter cela.
appelant npx <command>
quand <command>
n'est pas déjà dans votre $PATH
installera automatiquement un paquet avec ce nom du registre NPM pour vous, et l'invoquera. Quand c'est fait, le paquet installé ne sera pas n'importe où dans vos globals, donc vous n'aurez pas à vous soucier de la pollution à long terme. Vous pouvez prévenir ce comportement en fournissant --no-install
option.
pour npm < 5.2.0
, vous pouvez installer le paquet npx
manuellement en exécutant la commande suivante:
$ npm install -g npx
utilisez la commande npm bin
pour obtenir le node modules / bin répertoire de votre projet
$ $(npm bin)/<binary-name> [args]
p.ex.
$ $(npm bin)/bower install
Utiliser npm run[-script] <script name>
après avoir utilisé npm pour installer le paquet bin dans votre répertoire local ./node_modules
, modifiez package.json
pour ajouter <script name>
comme ceci:
$ npm install --save learnyounode
$ edit packages.json
>>> in packages.json
...
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"learnyounode": "learnyounode"
},
...
$ npm run learnyounode
ce serait bien si npm install avait une option --add-script ou quelque chose ou si npm exécutait fonctionnerait sans ajouter au bloc de scripts.
Utilisation npm-run
.
dans le readme:
npm-run
Trouver et exécuter des fichiers exécutables locaux de node_modules
tout exécutable disponible pour un script npm lifecycle est disponible pour npm-run
.
Utilisation
$ npm install mocha # mocha installed in ./node_modules
$ npm-run mocha test/* # uses locally installed mocha executable
Installation
$ npm install -g npm-run
Update: Je ne recommande plus cette méthode, à la fois pour les raisons de sécurité mentionnées et surtout pour la nouvelle commande npm bin
. Réponse originale ci-dessous:
comme vous l'avez découvert, tous les binaires installés localement sont dans ./node_modules/.bin
. Afin de toujours exécuter des binaires dans ce répertoire plutôt que des binaires disponibles dans le monde entier, s'ils sont présents, je vous suggère de mettre ./node_modules/.bin
en premier sur votre chemin:
export PATH="./node_modules/.bin:$PATH"
si vous mettez cela dans votre ~/.profile
, coffee
sera toujours ./node_modules/.bin/coffee
si disponible, sinon /usr/local/bin/coffee
(ou quel que soit le préfixe sous lequel vous installez des modules de noeuds).
la solution de chemin a le problème que si $(npm bin) est placé dans votre .profil./bashrc / etc il est évalué une fois et est défini pour toujours dans le répertoire dans lequel le chemin a été évalué pour la première fois. Si vous modifiez le chemin courant, votre chemin se développera à chaque fois que vous exécuterez le script.
pour contourner ces problèmes, je crée une fonction et je l'utilise. Il ne modifie pas votre environnement et est simple à utiliser:
function npm-exec {
$(npm bin)/$@
}
cela peut alors être utilisé comme ceci sans apporter aucun changement à votre environnement:
npm-exec r.js <args>
si vous voulez garder npm, alors npx devrait faire ce que vous avez besoin.
Si passer au fil (un remplacement npm par facebook) est une option pour vous, alors vous pouvez appeler:
yarn yourCmd
scripts à l'intérieur du paquet.json aura la priorité, si aucun n'est trouvé, il regardera à l'intérieur du dossier ./node_modules/.bin/
.
il affiche également ce qu'il a couru:
$ yarn tsc
yarn tsc v0.27.5
$ "/home/philipp/rate-pipeline/node_modules/.bin/tsc"
pour que vous n'ayez pas à configurer de scripts pour chaque commande dans votre package.json
.
si vous aviez un script défini à .scripts
dans votre package.json
:
"tsc": "tsc" // each command defined in the scripts will be executed from `./node_modules/.bin/` first
yarn tsc
serait équivalent à yarn run tsc
ou npm run tsc
:
yarn tsc
yarn tsc v0.27.5
$ tsc
si vous voulez que votre variable PATH soit mise à jour correctement à partir de votre répertoire courant, ajoutez ceci à la fin de votre équivalent .bashrc
(ou après tout ce qui définit 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
cela peut ajouter un court délai à chaque fois que l'invite bash est rendue (selon la taille de votre projet, très probablement), donc il est désactivé par défaut.
vous pouvez l'activer et le désactiver dans votre terminal en lançant node-mode
et node-mode-off
, respectivement.
je préfère ne pas compter sur des alias shell ou un autre paquet.
ajouter une ligne simple à scripts
section de votre package.json
, vous pouvez exécuter des commandes npm locales comme
npm run webpack
paquet.json
{
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"webpack": "webpack"
},
"devDependencies": {
"webpack": "^4.1.1",
"webpack-cli": "^2.0.11"
}
}
même solution acceptée par @regular, mais saveur de la coquille de poisson
if not contains (npm bin) $PATH
set PATH (npm bin) $PATH
end
Pour Windows
Stockez ce qui suit dans un fichier appelé npm-exec.bat
et ajoutez - le à votre %PATH%
@echo off
set cmd="npm bin"
FOR /F "tokens=*" %%i IN (' %cmd% ') DO SET modules=%%i
"%modules%"\%*
Utilisation
, Alors vous pouvez l'utiliser comme
npm-exec <command> <arg0> <arg1> ...
par exemple
pour exécuter wdio
installé dans le répertoire local node_modules, faire:
npm-exec wdio wdio.conf.js
c'est à dire, il sera exécuté .\node_modules\.bin\wdio wdio.conf.js
vous pouvez également utiliser direnv et changer la variable $PATH uniquement dans votre dossier de travail.
$ cat .envrc
> export PATH=$(npm bin):$PATH
ajoutez ce script à votre .bashrc
. Ensuite, vous pouvez appeler coffee
ou n'importe quoi localement. Ce qui est pratique pour votre ordinateur portable, mais ne l'utilisez pas sur votre serveur.
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 : ce script fait l'alias de la commande cd
, et après chaque appel de cd
il vérifie node_modules/.bin
et l'ajoute à votre $PATH
.
note2 : vous pouvez changer la troisième ligne en NODE_MODULES=$(npm bin);
. Mais cela rendrait la commande cd
trop lente.
Pour Windows utiliser ce:
/* cmd into "node_modules" folder */
"%CD%\.bin\grunt" --version
j'ai rencontré le même problème et je n'aime pas particulièrement utiliser des alias (comme régulier 's suggéré), et si vous ne les aimez pas trop alors voici un autre contournement que j'utilise, Vous devez d'abord créer un petit script de bash exécutable, dire 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 "$@"
et ensuite vous pouvez utiliser tous les exécutables de votre local /bin
en utilisant cette commande:
./setenv.sh <command>
./setenv.sh 6to5-node server.js
./setenv.sh grunt
si vous êtes utiliser scripts
dans le paquet.json:
...,
scripts: {
'start': './setenv.sh <command>'
}
j'aimerais savoir si c'est une mauvaise idée, mais après y avoir un peu réfléchi, Je ne vois pas de problème ici:
modifier la solution non sécurisée de Linus pour l'ajouter à la fin, en utilisant npm bin
pour trouver le répertoire, et faire que le script appelle npm bin
quand un package.json
est présent dans un parent (pour la vitesse), c'est ce que j'ai inventé pour 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
}
pour bash
, au lieu d'utiliser precmd
hook, vous pouvez utiliser la variable $PROMPT_COMMAND
(Je ne l'ai pas testé mais vous avez l'idée):
__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"
je suis un utilisateur Windows
et c'est ce qui a fonctionné pour moi:
// 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
Bonne Chance.
dans le cas où vous utilisez fish shell
et ne voulez pas ajouter à $path
pour des raisons de sécurité. Nous pouvons ajouter la fonction ci-dessous pour exécuter des exécutables de noeuds locaux.
### 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
Maintenant vous pouvez lancer chose comme:
n coffee
ou plus arguments comme:
n browser-sync --version
Note, si vous êtes un utilisateur de bash
, alors @Bob9630 réponses est la voie à suivre en utilisant bash $@
, qui n'est pas disponible dans fishshell
.
j'ai toujours utilisé la même approche que @guneysus pour résoudre ce problème, qui est de créer un script dans le paquet.fichier json et de l'utiliser à l'exécution de mnp exécuter le script de nom.
cependant, au cours des derniers mois, j'ai utilisé npx et je l'aime.
par exemple, j'ai téléchargé un projet Angular et je ne voulais pas installer le CLI Angular globalement. Ainsi, avec npx installé, au lieu d'utiliser la commande global angular cli (si Je l'avais installé) comme ceci:
ng serve
je peux le faire depuis la console:
npx ng serve
Comprennent le café-script dans le paquet.json avec la version spécifique requise dans chaque projet, typiquement comme ceci:
"dependencies":{
"coffee-script": ">= 1.2.0"
lancez ensuite npm install pour installer les dépendances dans chaque projet. Cela installera la version spécifiée de coffee-script qui sera accessible localement à chaque projet.