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 coffee est dans ./node_modules/.bin/coffee
. Est-il possible d'exécuter cette commande lorsque je me trouve dans le dossier principal de mon projet? Je suppose que je cherche quelque chose de similaire à bundle exec
dans le bundler. En gros, j'aimerais spécifier une version de coffee-script que toutes les personnes impliquées dans le projet devraient utiliser.
Je sais que je peux ajouter le drapeau -g
pour l'installer globalement afin que le café fonctionne bien n'importe où, mais que se passe-t-il si je souhaite avoir différentes versions de café par projet?
UPDATE: Comme le souligne Seyeong Jeong dans la réponse ci-dessous, depuis npm 5.2.0, vous pouvez utiliser npx [command]
, ce qui est plus pratique.
ANCIENNE RÉPONSE pour les versions antérieures à 5.2.:
Le problème avec la mise
./node_modules/.bin
dans votre CHEMIN, cela ne fonctionne que si votre répertoire de travail actuel est la racine de la structure de votre répertoire de projet (c'est-à-dire l'emplacement de node_modules
)
Indépendamment de votre répertoire de travail, vous pouvez obtenir le chemin des fichiers binaires installés localement avec
npm bin
Pour exécuter un binaire coffee
installé localement, indépendamment de l'endroit où vous vous trouvez dans la hiérarchie des répertoires du projet, vous pouvez utiliser cette construction bash
PATH=$(npm bin):$PATH coffee
J'ai appelé cela à npm-exec
alias npm-exec='PATH=$(npm bin):$PATH'
Alors maintenant je peux
npm-exec coffee
exécuter la copie correcte du café, peu 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
Vous n'avez plus besoin de manipuler $PATH
!
De [email protected]. , npm est fourni avec le package npx
qui vous permet d'exécuter des commandes à partir d'un node_modules/.bin
local. ou à partir d'un cache central.
Il suffit de lancer:
$ npx [options] <command>[@version] [command-arg]...
Par défaut, npx
vérifiera si <command>
existe dans $PATH
ou dans les fichiers binaires du projet local et l'exécutera.
Appeler npx <command>
lorsque <command>
ne figure pas déjà dans votre $PATH
installera automatiquement un paquet portant ce nom dans le registre NPM et l'invoquera. Une fois cela fait, le paquet installé ne sera plus dans vos globals, vous n’aurez donc pas à vous soucier de la pollution à long terme. Vous pouvez empêcher ce problème en fournissant l'option --no-install
.
Pour npm < 5.2.0
, vous pouvez installer le package npx
manuellement en exécutant la commande suivante:
$ npm install -g npx
Utilisez la commande npm bin
pour obtenir le répertoire modules/bin de votre projet.
$ $(npm bin)/<binary-name> [args]
par exemple.
$ $(npm bin)/bower install
Utilisez 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 l'installation de npm avait une option --add-script ou quelque chose du genre ou si l'exécution de npm fonctionnerait sans ajout au bloc de scripts.
Utilisez npm-run
.
Du readme:
Tout exécutable disponible dans un script de cycle de vie npm est disponible dans _npm-run
_.
_$ npm install mocha # mocha installed in ./node_modules
$ npm-run mocha test/* # uses locally installed mocha executable
_
_$ npm install -g npm-run
_
Mise à jour: Je ne recommande plus cette méthode, à la fois pour les raisons de sécurité mentionnées et pour la moindre des raisons, la commande npm bin
la plus récente. Réponse originale ci-dessous:
Comme vous l'avez découvert, tous les fichiers binaires installés localement se trouvent dans ./node_modules/.bin
. Afin de toujours exécuter les fichiers binaires dans ce répertoire plutôt que les fichiers binaires disponibles globalement, le cas échéant, je vous suggère de placer ./node_modules/.bin
en premier dans votre chemin:
export PATH="./node_modules/.bin:$PATH"
Si vous le mettez dans votre ~/.profile
, coffee
sera toujours ./node_modules/.bin/coffee
s'il est disponible, sinon /usr/local/bin/coffee
(ou le préfixe sous lequel vous installez les modules de noeud).
La solution PATH pose le problème suivant: si $ (npm bin) est placé dans votre fichier .profile/.bashrc/etc, il est évalué une fois et est défini pour toujours dans le répertoire dans lequel le chemin a été évalué. Si au lieu de cela vous modifiez le chemin actuel, alors chaque fois que vous exécutez le script, votre chemin se développe.
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)/$@
}
Ceci peut alors être utilisé comme ceci sans apporter de modifications à votre environnement:
npm-exec r.js <args>
Si vous voulez conserver npm, alors npx devrait faire ce dont vous avez besoin.
Si le passage au fil (un remplacement de npm par facebook) est une option pour vous, alors vous pouvez appeler:
yarn yourCmd
les scripts à l'intérieur de package.json auront la priorité; si aucun n'est trouvé, il regardera à l'intérieur du dossier ./node_modules/.bin/
.
Il affiche également ce qu'il a fonctionné:
$ yarn tsc
yarn tsc v0.27.5
$ "/home/philipp/rate-pipeline/node_modules/.bin/tsc"
Il n’est donc pas nécessaire de configurer des scripts pour chaque commande dans votre package.json
.
Si vous aviez un script défini sous .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
Je préfère ne pas compter sur les alias de Shell ou sur un autre package.
En ajoutant une simple ligne à la section scripts
de votre package.json
, vous pouvez exécuter des commandes npm locales telles que
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"
}
}
Si vous voulez que votre variable PATH se mette à jour correctement en fonction de votre répertoire de travail actuel, 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 (en fonction de la taille de votre projet, très probablement), de sorte qu'il est désactivé par défaut.
Vous pouvez l'activer et le désactiver dans votre terminal en exécutant respectivement node-mode
et node-mode-off
.
Vous pouvez utiliser:
npx <command>
npx
recherche une commande dans le répertoire .bin
si votre node_modules
Stockez les éléments suivants dans un fichier nommé 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%"\%*
Ensuite, vous pouvez l'utiliser comme npm-exec <command> <arg0> <arg1> ...
Par exemple
Pour exécuter wdio
installé dans le répertoire local node_modules, procédez comme suit:
npm-exec wdio wdio.conf.js
c'est-à-dire qu'il va exécuter .\node_modules\.bin\wdio wdio.conf.js
J'ai toujours utilisé la même approche que @guneysus pour résoudre ce problème, qui consiste à créer un script dans le fichier package.json et à l'utiliser avec npm run nom-script.
Cependant, au cours des derniers mois, j'ai utilisé npx et j'adore ça.
Par exemple, j'ai téléchargé un projet Angular et je ne voulais pas installer la CLI Angular. Donc, avec npx installé, au lieu d’utiliser la commande globale angular cli (si je l’avais installée) comme ceci:
ng serve
Je peux le faire depuis la console:
npx ng serve
Voici un article J'ai écrit sur NPX et cela va plus loin.
zxc est comme "bundle exec" pour nodejs. Cela revient à utiliser PATH=$(npm bin):$PATH
:
$ npm install -g zxc
$ npm install gulp
$ zxc which gulp
/home/nathan/code/project1/node_modules/.bin/gulp
Même solution acceptée par @normale, mais saveur de carapace de poisson
if not contains (npm bin) $PATH
set PATH (npm bin) $PATH
end
J'aimerais savoir si c'est une idée incertaine/mauvaise, mais après y avoir réfléchi un peu, je ne vois pas de problème ici:
Modification de la solution non sécurisée de Linus pour l'ajouter à la fin, en utilisant npm bin
pour trouver le répertoire, et en appelant uniquement le script npm bin
lorsqu'un package.json
est présent dans un parent (pour plus de rapidité), Voici ce que j'ai proposé pour 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
}
Pour bash
, au lieu d'utiliser le hook precmd
, vous pouvez utiliser la variable $Prompt_COMMAND
(je n'ai pas testé cela, mais vous en avez une 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"
Ajoutez ce script à votre .bashrc
. Ensuite, vous pouvez appeler coffee
ou n’importe lequel localement. C'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 crée une aliase 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.
Si vous utilisez fish Shell
et que vous 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 nœuds 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 exécuter des choses comme:
n coffee
ou plusieurs arguments comme:
n browser-sync --version
Notez que si vous êtes bash
utilisateur, @ Bob9630 répond est le meilleur choix en tirant parti de $@
de bash, qui n’est pas disponible dans fishshell
.
J'ai rencontré le même problème et je n'aime pas particulièrement utiliser les alias (comme suggéré par normal ), et si vous ne les aimez pas aussi, voici une autre solution de contournement que j'utilise, vous devez d'abord créez un petit script bash exécutable, dites 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 vous pouvez ensuite utiliser tous les exécutables de votre /bin
local en utilisant cette commande:
./setenv.sh <command>
./setenv.sh 6to5-node server.js
./setenv.sh grunt
Si vous utilisez scripts
dans package.json, alors:
...,
scripts: {
'start': './setenv.sh <command>'
}
Pour Windows, utilisez ceci:
/* cmd into "node_modules" folder */
"%CD%\.bin\grunt" --version
Vous pouvez également utiliser direnv et modifier la variable $ PATH uniquement dans votre dossier de travail.
$ cat .envrc
> export PATH=$(npm bin):$PATH
Je suis un utilisateur Windows
et voici 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.