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?

354
demandé sur kenorb 2012-03-13 11:31:06

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
450
répondu regular 2017-03-29 23:34:58

Nice example

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
231
répondu Seyeong Jeong 2018-03-01 03:28:28

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
84
répondu jassa 2014-12-13 01:18:55

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.

69
répondu jla 2018-08-25 15:33:01

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
43
répondu mightyiam 2016-10-28 21:20:46

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).

39
répondu Linus Gustav Larsson Thiel 2015-10-06 14:02:11

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>
23
répondu Bob9630 2015-08-17 21:09:42

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
18
répondu k0pernikus 2018-02-05 14:54:40

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.

6
répondu namuol 2013-11-11 06:14:10

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

5
répondu guneysus 2018-03-11 16:21:17

zxc est comme "bundle exec" pour nodejs. Il est similaire à l'utilisation de PATH=$(npm bin):$PATH :

$ npm install -g zxc
$ npm install gulp
$ zxc which gulp
/home/nathan/code/project1/node_modules/.bin/gulp
3
répondu Nathan 2016-01-18 22:09:23

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
3
répondu Pioneer Skies 2017-02-07 11:58:18

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

3
répondu Dheeraj Bhaskar 2017-11-15 11:38:27

vous pouvez également utiliser direnv et changer la variable $PATH uniquement dans votre dossier de travail.

$ cat .envrc
> export PATH=$(npm bin):$PATH
2
répondu Erem 2016-11-16 00:22:23

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.

2
répondu Tsutomu Kawamura 2017-01-26 02:25:48

Pour Windows utiliser ce:

/* cmd into "node_modules" folder */
"%CD%\.bin\grunt" --version
2
répondu b3wii 2017-02-22 16:35:08

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>'
}
1
répondu nkh 2017-05-23 11:55:10

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"
1
répondu Omar Diab 2016-08-23 05:30:17

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.

1
répondu Akash 2017-01-26 09:27:42

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 .

1
répondu Leon li 2017-05-19 16:45:51

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
0
répondu Jair Reina 2018-08-30 22:31:07

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.

-8
répondu almypal 2012-03-13 07:58:00