node_modulesにローカルにインストールされたパッケージの実行可能ファイルを使用する方法は?


493

でモジュールのローカルバージョンを使用するにはどうすればよいですかnode.js。たとえば、私のアプリでは、コーヒースクリプトをインストールしました。

npm install coffee-script

これはそれをインストールし./node_modules、coffeeコマンドはにあり./node_modules/.bin/coffeeます。プロジェクトのメインフォルダーにいるときにこのコマンドを実行する方法はありますか?私bundle execはbundlerのようなものを探していると思います。基本的に、プロジェクトに関係するすべての人が使用する必要があるコーヒースクリプトのバージョンを指定します。

-gフラグを追加してグローバルにインストールできることを知っているので、コーヒーはどこでも問題なく機能しますが、プロジェクトごとに異なるバージョンのコーヒーを用意したい場合はどうなりますか?


9
命令の多くは、私のようなと言う事読みnpm install niftycommand、その後にniftycommand。しかし、パスに./node_modules/.binがない限り、これは機能しません。
Bennett McElwee 2016

2
ここには非常に優れた記述があります:firstdoit.com/…—基本的に、後でターミナルからnpm run build`のようcoffeeに、コマンドをnpm scriptsセクションに入れることをお勧めします"build": "coffee -co target/directory source/directoy", so you can run
ベニー

@BennyNeugebauer確かに、それは私がPATHを
いじるの

12
medium.com/@maybekatz/…にnpx付属する使用npm 5.2.0
onmyway133

回答:


568

更新:Seyeong Jeongが以下の回答で指摘しているように、npm 5.2.0から使用できるためnpx [command]、より便利です。

5.2.0より前のバージョンの古い回答

置くことの問題

./node_modules/.bin

PATHには、現在の作業ディレクトリがプロジェクトディレクトリ構造のルート(つまり、の場所node_modules)である場合にのみ機能します。

作業ディレクトリとは無関係に、ローカルにインストールされたバイナリのパスを取得できます

npm bin

coffeeプロジェクトディレクトリ階層のどこにいても、ローカルにインストールされたバイナリを実行するには、このbash構成を使用できます

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

17
さらに一歩先に進むこともできますalias coffee="npm-exec coffee"
通常の

6
別のプロジェクトにcdすると、出力が変化します。プロジェクト内でcdしても変化しません。npm bin「祖先ディレクトリ」からcwdまでのチェーンでnode_modulesディレクトリを検索します。これは、プロジェクトのpackage.jsonにリストされているモジュールのバイナリを具体的に使用する場合に、まさに望ましい動作です。
定期的

11
あれまあ!ローカルモジュールを機能させるために、本当にそのようなことを行う必要がありますか?それをチームに説明することは非常に現実的ではありません!もう少し簡単なことはありませんか?
Alexian

17
npmスクリプトは常にローカルバイナリを最初に検索するため、いつでも使用できます。そこで、バイナリのそれぞれにエイリアスを設定するか、「build」などの一般的な名前を使用できます。
Joe Zim、2015

6
@philosodad、実際には違います、あなたは違います。PATHそれがコマンド呼び出しの前にあったものに戻ってきます。コマンドを実行する前に同じ行で環境変数を設定すると、そのコマンドの環境にのみ影響します。
定期的に

410

いい例

$PATHもう操作する必要はありません!

npm@5.2.0からNPMに付属npxローカルからコマンドを実行することができますパッケージnode_modules/.binまたは中央キャッシュから。

単に実行する:

$ npx [options] <command>[@version] [command-arg]...

デフォルトでは、 npxはは、またはローカルプロジェクトバイナリに<command>存在するかどうかを確認し$PATH、それを実行します。

npx <command>いつ電話するか<command>がまだ入っていない$PATHと、その名前のパッケージがNPMレジストリから自動的にインストールされ、呼び出されます。完了すると、インストールされたパッケージはグローバルのどこにも存在しないため、長期的に汚染を心配する必要はありません。--no-installオプションを提供することにより、この動作を防ぐことができます。

の場合npm < 5.2.0npx次のコマンドを実行して手動でパッケージをインストールできます。

$ npm install -g npx

1
サードパーティのグローバルnpmパッケージをインストールするのは好きではありませんがnpmpackage.jsonほぼ同じ機能を提供します。
guneysus

「パスは文字列である必要があります。未定義で受信されました」というメッセージが表示された場合、修正は次のとおり
Valeriy

1
この答えはいいです。しかし、私が言いたいのnpxはラメだ。それはされている必要がありますnpm runnpm execまたは何か。
William Entriken

@WilliamEntriken何らかの理由でnpm run [my-local-package]、Ubuntuで動作していませんが、Windowsデバイスでは動作しているようです。
時計仕掛け

97

npm binコマンドを使用して、プロジェクトのノードモジュール/ binディレクトリを取得します。

$ $(npm bin)/<binary-name> [args]

例えば

$ $(npm bin)/bower install

4
このシンプルで汎用的なソリューションが気に入っています。エイリアスが不要に見えるようにします。
Matt Montag、2015年

エレガントで安全な次善のソリューションと思われますexport PATH="./node_modules/.bin:$PATH"
jontsai

1
@ inf3rnoコマンドは$(npm bin)/jasmine、ではありませんnode $(npm bin)/jasmine(たぶんあなたはそれを理解しましたが、他の人のために明確にしています)。
jassa

5
悪い解決策ではありませんが、$を使用した標準のWindowsコマンドラインでは実行できません。それをより互換性があるので、package.jsonスクリプトセクションに置くことは、私が感じるより良いアプローチです。
ティモシーゴンザレス

77

使用する 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 install依存関係にアクセスできます。唯一のマイナーな欠点は、あなたがする必要があるnpm run eslint(または何でも)ことです。gulpを実行する「start」というスクリプトを作成して、入力するだけで開発npm startサーバーを起動できます。かなりクールなものであり、bashの良さはないので、Windowsの友達はまだあなたを好きです。:)
jpoveda 2015

1
$(npm bin)をパスに配置するためのエイリアスを追加するのは賢明ですが、これがローカル構成のない人でも機能するという事実は私の心に
残り

12
これにはもっと投票が必要です!次の--ように引数をスクリプトに渡します:npm run learnyounode -- --normal-switches --watch -d *.js
ptim

これも最良の解決策だと思います。ここでの詳細な説明があります:lostechies.com/derickbailey/2012/04/24/...
adampasz

1
これは私が普段行っていることですが、いくつかの理由により、Ubuntuデバイスでnpm run ts-nodeは機能しません。私はnpxに再ソートする必要があります。
時計じかけ

42

を使用しnpm-runます。

Readmeから:

npm-run

node_modulesからローカル実行可能ファイルを見つけて実行する

npmライフサイクルスクリプトで使用できる実行可能ファイルはすべて、で使用できますnpm-run

使用法

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

取り付け

$ npm install -g npm-run

8
もはや、上記のnpxを参照してください... stackoverflow.com/a/45164863/3246805
tj

41

更新:言及されたセキュリティ上の理由と新しいものの両方のため、私はこの方法をもはやお勧めしませんnpm binコマンドだけで。以下の元の答え:

ご存知のとおり、ローカルにインストールされたバイナリはすべてにあり./node_modules/.binます。グローバルに利用可能なバイナリではなく、常にこのディレクトリでバイナリを実行するために、存在する場合./node_modules/.binは、パスの最初に置くことをお勧めします。

export PATH="./node_modules/.bin:$PATH"

これをに入れた場合~/.profilecoffee常に./node_modules/.bin/coffee使用可能になります。そうでない場合/usr/local/bin/coffee(またはノードモジュールをインストールするときに使用するプレフィックス)


1
それがおそらく最良の解決策です。また、私は私のプロジェクトでは、「時計」と呼ばれるbashスクリプトを作成しました:./node_modules/.bin/coffee --output lib/ --compile --bare --watch src
typeoneerror

72
危険、ウィル・ロビンソン!$ PATHで相対パスを使用すると、特に最初のアイテムとして真上に置くと、惑星のサイズのセキュリティホールが開きます。あなたがいるディレクトリが誰でも書き込み可能である場合には(どこかで言って/tmp、任意のプロセスやユーザーは、通常のコマンドの悪質なバージョン(のように置くことによって、あなたのセッションをハイジャックすることができます)lscpなど)があります。これらは、パスワードなどをキャプチャする「見えない」サブシェルを生成する可能性があります。
2014

ルートでのみ機能し、他の場所では機能しません。alias npm-exec='PATH=$(npm bin):$PATH'スリッカーです。
オリゴフレン

1
これをあなたの最初の要素としてではPATHなく、最後の要素として($(npm bin)フォームを使用して)配置しない場合、これはどれほど悪いことですか?そのため、既存のものを上書きできずnpm binPATHvarに関係なく、ディレクトリ内の実行可能ファイルをすでに信頼しているはずです。脅威モデルは、a)悪意のある誰かがファイルシステムにアクセスし、b)それらがそれらのシステムツールに近い名前の実行可能ファイルを追加し、c)入力ミスをするというものですか?npm-installedプログラムを使用するときに外部の実行可能ファイルをすでに信頼している場合、これを悪化させるシナリオを理解しようとします。
osdiab

あなたはエイリアスでシェルトリックを行うことができ、手動でパスすることができ、これは「機能します」が、それは非常に理想的ではありません。
killscreen

22

PATHソリューションには、$(npm bin)が.profile / .bashrc / etcに配置されている場合、一度評価され、パスが最初に評価されたディレクトリに永久に設定されるという問題があります。代わりに現在のパスを変更すると、スクリプトを実行するたびに、パスが大きくなります。

これらの問題を回避するために、関数を作成して使用しました。環境を変更せず、簡単に使用できます。

function npm-exec {
   $(npm bin)/$@  
}

これは、環境に変更を加えることなく、次のように使用できます。

npm-exec r.js <args>

2
私はこれが好き!私は単に自分の関数に名前を付けましたn
jontsai '9/09/15

これは素晴らしい!共有いただきありがとうございます。下に魚の殻のバージョンを追加しました。
LeOn-Han Li '19年

22

npmを維持したい場合は、npxが必要なことを行う必要があります。


糸に切り替える(facebookによるnpmの交換)がオプションの場合は、次のように呼び出します

 yarn yourCmd

package.json内のスクリプトが優先され、見つからない場合は./node_modules/.bin/フォルダー内を検索します。

また、実行した内容も出力します。

$ yarn tsc
yarn tsc v0.27.5
$ "/home/philipp/rate-pipeline/node_modules/.bin/tsc"

したがって、の各コマンドにスクリプトを設定する必要はありませんpackage.json


.scripts内部でスクリプトが定義されている場合package.json

"tsc": "tsc" // each command defined in the scripts will be executed from `./node_modules/.bin/` first

yarn tscyarn run tscまたはと同等npm run tscです:

 yarn tsc
 yarn tsc v0.27.5
 $ tsc

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


これは、複数の引数を渡す場合は機能しません。たとえば、npm-exec gulp <some_task>
OK999

@ OK9999いくつかの小さな変更により、引数を渡すことができると確信しています(ここで渡すと、 ""で囲まれているためです)。私が提案するのは、gulpファイルをbinからプロジェクトルートにコピーアンドペーストすることです(ファイルの一部を変更する必要がありますが、新しいコードを記述しなくても機能します)
Dheeraj Bhaskar

はい、そうしました。node_modulesフォルダーはgulpfileが存在するフォルダーにある必要があります
OK999

7

私はシェルのエイリアスや他のパッケージに依存しないことを好みます。

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

5

現在の作業ディレクトリに基づいてPATH変数を正しく更新する場合は、これを.bashrc-equivalent の最後に(またはを定義するものの後に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-modenode-mode-offをそれぞれ実行して、端末内で有効または無効にできます。


4

私は常にこの問題を解決するために@guneysusと同じアプローチを使用してきました。つまり、package.jsonファイルにスクリプトを作成し、それをnpm run script-nameで実行します。

ただし、ここ数カ月はnpxを使用していますを気に入っています。

たとえば、Angularプロジェクトをダウンロードしましたが、Angular CLIをグローバルにインストールしたくありませんでした。したがって、npxがインストールされている場合は、次のように(インストールしていた場合)グローバルなcliコマンドを使用する代わりに、

ng serve

コンソールからこれを行うことができます:

npx ng serve

これが私がNPXについて書いた記事で、それはさらに深く入ります。


2

zxcは、nodejsの「bundle exec」に似ています。これは次のように使用しPATH=$(npm bin):$PATHます。

$ npm install -g zxc
$ npm install gulp
$ zxc which gulp
/home/nathan/code/project1/node_modules/.bin/gulp


1

direnvを使用して、作業フォルダー内の$ PATH変数のみを変更することもできます。

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

1

このスクリプトをに追加します.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 "$@";
  add_local_node_modules_to_path;
}

add_local_node_modules_to_path;

:このスクリプトはcdコマンドのエイリアスを作成し、呼び出しのたびcdにチェックnode_modules/.binして自分の$PATH

注2:3行目をに変更できますNODE_MODULES=$(npm bin);。しかし、それではcdコマンドが遅くなりすぎます。


1
$(npm bin)ハードコーディングの代わりに使用し./node_modules/.binます。
bfontaine 2017年

うーん、$(npm bin)cdコマンドで使用するには遅すぎるようです。コードを復元し、メモを追加しました。
川村勉2017年

1

Windowsの場合、これを使用します。

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

0

私は同じ問題に遭遇し、エイリアスを使用するのは特に好きではありません(通常のが推奨するように)。また、エイリアスが好きではない場合は、ここで私が使用する別の回避策として、最初に小さな実行可能なbashスクリプトを作成する必要があります。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 "$@"

次に、次の/binコマンドを使用して、ローカルで実行可能ファイルを使用できます。

./setenv.sh <command>
./setenv.sh 6to5-node server.js
./setenv.sh grunt

scriptspackage.jsonで使用している場合:

...,
scripts: {
    'start': './setenv.sh <command>'
}

2
このsetenvスクリプトは、package.jsonスクリプトには必要ありません。npm run {scripts}を実行すると、npmはすでにローカルnode_modules / .binディレクトリをパスの前に付加します。
jasonkarns、2015

0

これが安全でない/悪い考えであるかどうか知りたいのですが、少し考えた後、ここでは問題が見つかりません。

Linusの安全でないソリューションを変更して最後に追加し、を使用npm binしてディレクトリを検索し、スクリプトが親に存在する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
}

の場合bashprecmdフックを使用する代わりに、$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"

npm bin末尾に追加して$PATHも、ユーザーが期待するとおりに実行されない可能性があります。基本的には別の実行可能ファイルですが、おそらくグローバルにインストールされた別のバージョンのパッケージです。
LoganMzz 2017年

0

私は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

幸運を。


0

セキュリティ上の理由で使用fish shellしていて、追加したくない場合$path。以下の関数を追加して、ローカルノードの実行可能ファイルを実行できます。

### 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を$@利用する方法fishshellです。これはで利用できません。


-9

通常は次のように、package.jsonに各プロジェクトで必要な特定のバージョンを含むコーヒースクリプトを含めます。

"dependencies":{
  "coffee-script": ">= 1.2.0"

次に、npm installを実行して、各プロジェクトに依存関係をインストールします。これにより、指定したバージョンのcoffee-scriptがインストールされ、各プロジェクトからローカルにアクセスできるようになります。


ええ、私の質問で述べたように、私はそれまでにそれを得ました。プロジェクトで./node_modules/.bin/coffee以外のものを具体的にどのように呼び出すのですか?
typeoneerror 2012年

プロジェクトのメインフォルダーにpackage.jsonを指定してnpm installを実行した場合、このフォルダーに./node_modules/.bin/coffeeフォルダーがあるはずです。./node_modules/coffee-script/bin/coffeeを使用すると、ローカルバージョンのcoffeeが実行されますが、coffeeを実行するだけでグローバルインストールが実行されます。このプロジェクトフォルダー内の別のパスに別のバージョンのコーヒーがインストールされている場合は、。/ path / to / this / installation / coffeeを使用してそれにアクセスできます。
almypal 2012年

これは私にはうまくいきませんでした。「svgo」を使用しようとしていますが、グローバルにインストールした場合にのみ機能します。私はpackage.json npm install svgoと同様に試しましたnpm install。どちらの方法でも「正常に」インストールされましたが、「svgo」コマンドはまだ使用できません。
Ryan Wheale 2013

1
Gruntはこれを巧妙な方法で使用し、IMHOは他のパッケージも使用します。最初にgrunt-cliパッケージをグローバルにインストールし、次にプロジェクトディレクトリにgruntパッケージの(変更された)バージョンをインストールします。次にを実行するとgrunt、このローカルバージョンが使用されます。
2014
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.