如何使用在node_modules本地安装的软件包?
如何在node.js
使用本地版本的模块。 例如,在我的应用程序中,我安装了咖啡脚本:
npm install coffee-script
这将它安装在./node_modules
,并且coffee命令在./node_modules/.bin/coffee
。 当我在我的项目的主文件夹中有没有办法运行这个命令? 我想我正在寻找类似bundle exec
东西。 基本上,我想指定一个与项目有关的每个人都应该使用的咖啡脚本的版本。
我知道我可以添加-g
标志来全局安装它,所以咖啡在任何地方都能正常工作,但是如果我想为每个项目使用不同版本的咖啡,该怎么办?
推杆的问题
./node_modules/.bin
进入你的PATH的是,它只有当你的工作目录是你的项目目录结构的根(即node_modules
的位置)
独立于你的工作目录,你可以得到本地安装的二进制文件的path
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
使用npm bin
命令获取项目的节点modules / bin目录
$ $(npm bin)/<binary-name> [args]
例如
$ $(npm bin)/bower install
使用npm run[-script] <script name>
使用npm将bin软件包安装到本地./node_modules目录后,修改package.json来添加,如下所示:
$ 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不需要添加脚本块就可以工作,那将会很好。
更新:我不再推荐这种方法,既出于提到的安全原因,也不是至less新的npm bin
命令。 下面的原始答案:
正如您发现的那样,任何本地安装的二进制文件都位于./node_modules/.bin
。 为了总是在这个目录中运行二进制文件,而不是全局可用的二进制文件(如果存在的话),我build议你./node_modules/.bin
放在你的path中:
export PATH="./node_modules/.bin:$PATH"
如果你把它放在你的~/.profile
,那么coffee
将永远是./node_modules/.bin/coffee
,否则/usr/local/bin/coffee
(或者你正在安装节点模块的前缀)。
使用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
你不必操纵$PATH
了!
从npm@5.2.0开始 , npm提供了npx包,允许您从本地node_modules/.bin
或中央caching运行命令。
只需运行:
$ npx [options] <command>[@version] [command-arg]...
默认情况下, npx
将检查$PATH
是否存在<command>
,或者在本地项目二进制文件中执行该命令。
当<command>
不在$PATH
时调用npx <command>
会自动从NPMregistry中为你安装一个名称为package的包,并调用它。 完成后,已安装的软件包将不会在您的全球任何地方,所以您不必长期担心污染。 您可以通过提供--no-install
选项来防止此行为。
对于npm < 5.2.0
,您可以通过运行以下命令来手动安装npx
软件包:
$ npm install -g npx
PATH解决scheme的问题是,如果$(npm bin)被放置在你的.profile / .bashrc / etc目录中,那么它会被评估一次,永远被设置为path被首先评估的目录。如果改为修改当前path,每次运行脚本时,path都会增长。
为了解决这些问题,我创build了一个函数并使用它。 它不会修改您的环境,使用简单:
function npm-exec { $(npm bin)/$@ }
这可以像这样使用,而不需要对环境做任何改变:
npm-exec r.js <args>
如果您希望您的PATHvariables根据您当前的工作目录正确更新,请将其添加到.bashrc
-eivaivalent(或定义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
来启用和禁用terminal。
对于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> ...
一样使用它npm-exec <command> <arg0> <arg1> ...
例如
要执行安装在本地node_modules目录中的wdio,请执行wdio
操作:
npm-exec wdio wdio.conf.js
即它将运行.\node_modules\.bin\wdio wdio.conf.js
您也可以使用direnv,并只在工作文件夹中更改$ PATHvariables。
$ cat .envrc > export PATH=$(npm bin):$PATH
将这个脚本添加到你的.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
命令太慢。
相同@regular的可接受的解决scheme,但鱼贝壳的味道
if not contains (npm bin) $PATH set PATH (npm bin) $PATH end
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
我很想知道这是不是一个不安全/不好的想法,但是想一想,我在这里没有看到一个问题:
修改Linus的不安全的解决scheme,将其添加到最后,使用npm bin
来查找目录,并使脚本仅在package.json
存在于父级(为了速度)时调用npm bin
,这就是我想出的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
,可以使用$PROMPT_COMMAND
variables(我没有testing过这个,但是你有这个想法),而不是使用precmd
钩子:
__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"
我是一个Windows
用户,这是我的工作:
// First set some variable - ie replace is with "xo" D:\project\root> set xo="./node_modules/.bin/" // Next, work with it D:\project\root> %xo%/bower install
祝你好运。
如果切换到纱线(Facebook的npm更换)是你的select,那么你可以打电话给:
yarn yourCmd
package.json中的脚本优先,如果没有find它,它将在./node_modules/.bin/
文件夹中查找。
它也输出它运行的内容:
$ yarn tsc yarn tsc v0.27.5 $ "/home/philipp/rate-pipeline/node_modules/.bin/tsc"
所以你不必为package.json
每个命令设置脚本。
如果您在package.json
中的.scripts
定义了一个脚本:
"tsc": "tsc" // each command defined in the scripts will be executed from `./node_modules/.bin/` first
yarn tsc
相当于yarn run tsc
或npm run tsc
:
yarn tsc yarn tsc v0.27.5 $ tsc
我遇到了同样的问题,我不是特别喜欢使用别名(如常规的build议),如果你不喜欢他们,那么这里是另一个我使用的解决方法,你首先必须创build一个微小的可执行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
如果你在package.json中使用scripts
,那么:
..., scripts: { 'start': './setenv.sh <command>' }
对于Windows使用这个:
/* cmd into "node_modules" folder */ "%CD%\.bin\grunt" --version
如果你正在使用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
不可用。
在package.json中包含咖啡脚本和每个项目所需的特定版本,通常如下所示:
"dependencies":{ "coffee-script": ">= 1.2.0"
然后运行npm install在每个项目中安装依赖项。 这将安装咖啡脚本的指定版本,每个项目都可以在本地访问。