web-dev-qa-db-fra.com

Comment utiliser le paquet installé localement dans node_modules?

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?

429
typeoneerror

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
509
regular

Nice example

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
335
Seyeong Jeong

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
89
jassa

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.

74
jla

Utilisez npm-run .

Du readme:

npm-run

Rechercher et exécuter des exécutables locaux à partir de node_modules

Tout exécutable disponible dans un script de cycle de vie npm est disponible dans _npm-run_.

Usage

_$ npm install mocha # mocha installed in ./node_modules
$ npm-run mocha test/* # uses locally installed mocha executable 
_

Installation

_$ npm install -g npm-run
_
42
mightyiam

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>
22
Bob9630

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
19
k0pernikus

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

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.

5
namuol

update: Si vous êtes sur le dernier NPM (version> 5.2)

Vous pouvez utiliser:

npx <command>

npx recherche une commande dans le répertoire .bin si votre node_modules

ancienne réponse:

Pour les fenêtres

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%"\%*

Usage

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

5
Dheeraj Bhaskar

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.

5
Jair Reina

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
2
Nathan

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
2
Pioneer Skies

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"
1
osdiab

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.

1
Tsutomu Kawamura

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.

1
LeOn - Han Li

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>'
}
1
nkh

Pour Windows, utilisez ceci:

/* cmd into "node_modules" folder */
"%CD%\.bin\grunt" --version
1
b3wii

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

$ cat .envrc
> export PATH=$(npm bin):$PATH
1
Erem

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.

1
Akash