640

如何在node.js. 例如,在我的应用程序中,我安装了咖啡脚本:

npm install coffee-script

这将其安装在./node_modules并且咖啡命令在./node_modules/.bin/coffee. 当我在项目的主文件夹中时,有没有办法运行这个命令?我想我正在寻找类似于捆绑器的东西bundle exec。基本上,我想指定一个涉及项目的每个人都应该使用的咖啡脚本版本。

我知道我可以添加-g标志以在全球范围内安装它,这样咖啡在任何地方都可以正常工作,但是如果我想为每个项目提供不同版本的咖啡怎么办?

4

24 回答 24

680

更新:正如 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
于 2013-03-01T12:06:03.517 回答
528

很好的例子

你不必再操纵$PATH了!

npm@5.2.0 开始npm附带了npx一个包,它允许您从本地node_modules/.bin或中央缓存运行命令。

只需运行:

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

默认情况下,npx将检查是否<command>存在于$PATH或本地项目二进制文件中,然后执行。

调用npx <command>when <command>is not already in your$PATH将自动从 NPM 注册表中为你安装一个具有该名称的包,并调用它。完成后,已安装的包将不会在您的全局变量中的任何位置,因此您不必担心长期污染。您可以通过提供--no-install选项来防止这种行为。

对于,您可以通过运行以下命令手动npm < 5.2.0安装包:npx

$ npm install -g npx
于 2017-07-18T10:59:41.750 回答
116

使用npm bin命令获取你项目的node modules /bin目录

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

例如

$ $(npm bin)/bower install
于 2014-12-13T01:18:55.837 回答
84

利用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 可以在不添加到脚本块的情况下工作,那就太好了。

于 2015-02-16T20:10:51.973 回答
45

更新:如果您使用的是最近的 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

于 2016-08-03T23:00:09.090 回答
43

更新:我不再推荐这种方法,既是出于上述安全原因,也不是最不推荐的新npm bin命令。原答案如下:

正如您所发现的,任何本地安装的二进制文件都位于./node_modules/.bin. 为了始终在此目录中运行二进制文件而不是全局可用的二进制文件(如果存在),我建议您将./node_modules/.bin路径放在首位:

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

如果你把它放在你的~/.profile,如果可用的话,coffee总是会./node_modules/.bin/coffee出现,否则/usr/local/bin/coffee(或者你正在安装节点模块的任何前缀)。

于 2012-03-13T11:52:21.357 回答
43

使用npm-run.

从自述文件:

npm-运行

从 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
于 2016-10-28T21:20:46.050 回答
25

如果你想保留 npm,那么npx应该做你需要的。


如果您可以选择切换到 yarn(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 tsc相当于yarn run tscor npm run tsc

 yarn tsc
 yarn tsc v0.27.5
 $ tsc
于 2017-08-11T10:54:04.070 回答
23

PATH 解决方案的问题是,如果将 $(npm bin) 放置在您的 .profile/.bashrc/etc 中,它会被评估一次,并且永远设置为首先评估路径的目录。如果改为修改当前路径,则每次运行脚本时,您的路径都会增长。

为了解决这些问题,我创建了一个函数并使用了它。它不会修改您的环境并且易于使用:

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

然后可以像这样使用它,而无需对您的环境进行任何更改:

npm-exec r.js <args>
于 2015-08-17T21:09:42.460 回答
12

TL;DR:npm exec与. 一起使用npm@>=7


其他答案中提到的npx命令已被完全重写,npm@7默认情况下附带node@15并可以安装在node@>=10. 该实现现在等于新引入的命令,与之前的命令实现npm exec类似但不等于。npx

一个区别是,例如它总是交互地询问是否应该在尚未安装依赖项时下载它(也可以用 params--yes或覆盖--no)。

这是一个例子npm exec。双破折号 ( --) 将npm exec参数与实际的命令参数分开:

npm exec --no -- jest --coverage

另请参阅npm exec.

于 2021-03-12T17:31:12.653 回答
9

我宁愿不依赖 shell 别名或其他包。

scripts在部分添加一个简单的行package.json,您可以运行本地 npm 命令,例如

npm run webpack

包.json

{
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "webpack": "webpack"
  },
  "devDependencies": {
    "webpack": "^4.1.1",
    "webpack-cli": "^2.0.11"
  }
}
于 2018-03-11T16:21:17.030 回答
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-mode和在终端中启用和禁用它。node-mode-off

于 2013-11-11T06:14:10.797 回答
5

我一直使用与@guneysus 相同的方法来解决这个问题,即在 package.json 文件中创建一个脚本并使用它运行 npm run script-name。

然而,最近几个月我一直在使用npx,我喜欢它。

例如,我下载了一个 Angular 项目,但我不想全局安装 Angular CLI。因此,安装了 npx,而不是像这样使用全局 angular cli 命令(如果我安装了它):

ng serve

我可以从控制台执行此操作:

npx ng serve

这是我写的一篇关于 NPX 的文章,对此进行了更深入的探讨。

于 2018-08-30T22:31:07.363 回答
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
于 2016-01-18T22:09:23.687 回答
2

相同的 @regular 接受的解决方案,但鱼壳风味

if not contains (npm bin) $PATH
    set PATH (npm bin) $PATH
end
于 2015-09-08T14:42:49.817 回答
1

对于 Windows,请使用:

/* cmd into "node_modules" folder */
"%CD%\.bin\grunt" --version
于 2017-02-02T12:59:18.617 回答
1

将此脚本添加到您的.bashrc. 然后你可以coffee在本地打电话或打电话。这对您的笔记本电脑很方便,但不要在您的服务器上使用它。

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:您可以将第三行更改为NODE_MODULES=$(npm bin);. 但这会使cd命令太慢。

于 2016-12-19T16:49:30.747 回答
1

You can also use direnv and change the $PATH variable only in your working folder.

$ cat .envrc
> export PATH=$(npm bin):$PATH
于 2016-11-16T00:22:23.947 回答
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

如果您scripts在 package.json 中使用,则:

...,
scripts: {
    'start': './setenv.sh <command>'
}
于 2014-12-30T22:20:43.083 回答
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

祝你好运。

于 2017-01-26T09:27:42.230 回答
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.

于 2017-05-19T16:29:01.160 回答
0

我很想知道这是否是一个不安全/坏主意,但经过一番思考后,我认为这里没有问题:

修改 Linus 的不安全解决方案以将其添加到末尾,npm bin用于查找目录,并使脚本仅在父级中存在 anpm 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
}

对于bash,而不是使用precmd钩子,你可以使用$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"
于 2016-07-15T01:48:32.360 回答
0

我提出了我开发的新解决方案 (05/2021)

您可以使用 lpx https://www.npmjs.com/package/lpx

  • 运行在本地 node_modules/.bin 文件夹中找到的二进制文件
  • 从工作空间中的任何位置运行在工作空间根目录的 node_modules/.bin 中找到的二进制文件

如果在本地找不到二进制文件,lpx 不会下载任何包(即不像 npx)

示例: lpx tsc -b -wtsc -b -w使用本地 typescript 包运行

于 2021-05-16T11:11:32.280 回答
-11

在 package.json 中包含 coffee-script 以及每个项目所需的特定版本,通常如下所示:

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

然后运行 ​​npm install 在每个项目中安装依赖项。这将安装指定版本的咖啡脚本,每个项目都可以在本地访问它。

于 2012-03-13T07:58:00.143 回答