我是节点js的新手。我正在尝试构建一个npm模块,并将/node_modules/.bin文件夹中的cmd文件与本地软件包的名称混淆。
我安装了多个包作为依赖项,发现cmd文件不同。
jade.cmd
@IF EXIST "%~dp0\node.exe" (
"%~dp0\node.exe" "%~dp0\..\jade\bin\jade" %*
) ELSE (
@SETLOCAL
@SET PATHEXT=%PATHEXT:;.JS;=;%
node "%~dp0\..\jade\bin\jade" %*
)
摩卡casperjs.cmd
@IF EXIST "%~dp0\/bin/sh.exe" (
"%~dp0\/bin/sh.exe" "%~dp0\..\mocha-casperjs\bin\mocha-casperjs" %*
) ELSE (
@SETLOCAL
@SET PATHEXT=%PATHEXT:;.JS;=;%
/bin/sh "%~dp0\..\mocha-casperjs\bin\mocha-casperjs" %*
)
我的问题是,如果它是由NPM自动生成的,为什么npm为2个不同的包创建2个不同的文件。是用户创建并告诉NPM的东西吗?
答案 0 :(得分:4)
<强> TL;博士强>
在Windows上,npm
根据脚本文件的 shebang行中指定的shell /解释器创建包装批处理文件(*.cmd
)。强>
您所看到的是 npm模拟 Windows 的 Unix shebang机制,其中第一行是一个可执行的纯文本文件(脚本),如果以魔术字符#!
开头,则告诉操作系统将脚本传递给执行的解释器/ shell(请参阅我的this answer以获取更多信息)。
由于Windows不支持shebang行,npm
会创建一个包装器 *.cmd
(批处理)文件,该文件显式调用“二进制”文件(指定的脚本文件)在bin
的{{1}}键中,在脚本文件的shebang行中指定了任何可执行文件。
换句话说: package.json
解析脚本的shebang行以确定要调用的shell /解释器,并相应地创建包装器批处理脚本。
如果我们在npm
包中查看./bin/jade.js
,我们会看到jade
为shebang行,这就是#!/usr/bin/env node
包装文件调用jade.cmd
的原因。
这是典型案例:用JavaScript编写的脚本,必须由Node.js引擎执行。
但是,也可以指定任何其他shell /解释器,但这样做只有在 Windows <上也可以使用给定的shell /解释器时才有意义/强>;对于node.exe
,这是给定的,但是,正如node
的内容所示,使用 Unix默认shell ,mocha-casper.cmd
({包/bin/sh
中的{1}}文件包含shebang行./bin/mocha-casperjs
)。
mocha-casper.js
的制造商选择通过重新实现将#!/bin/sh
的Unix shell脚本作为mocha-casperjs
来推广自己的Windows集成(也是批处理文件) - 但是,由于cmd.exe
没有意识到这一点,因此该批处理文件不会放在PATH(全局)/不能仅通过名称发现(在项目上下文中调用CLI时)。
更一般地说,脚本也适用于Windows,使用shebang行与绝对,POSIX风格的路径 没有意义 - EXCEPT 如果目标shell /解释器是通过mocha-casperjs.bat
的 间接调用指定的,它会向npm
发出信号,表明它应该被查找在PATH中(再次,请参阅我的this answer了解更多信息)
(此外,包装器批处理文件也在其自己的目录中查找可执行文件,但这很少有用,因为即使您明确将它们添加为/usr/bin/env
也不会将它们复制到那里您npm
的{{1}}密钥中的条目。)
顺便说一下:npm
的最新版本还为Unix环境创建无扩展包装脚本,特别是Cygwin和Windows上的Ubuntu上的Bash。
创建自己的软件包时,对于CLI(“二进制文件”) - 直接可执行的脚本,其作用类似于命令行实用程序 - 也是在Windows上运行的npm软件包的一部分,你必须:
在脚本中添加一个shebang行 - 即使您只打算在Windows上运行它们。
将shebang行定义为package.json
;通常 - 如果您的脚本是用JavaScript编写的,并且必须使用bin
执行 - 请使用:
npm
在 #!/usr/bin/env <interpreter-executable-filename-without-extension>
文件的node
密钥中,定义脚本的密钥,不带扩展名。,因为#!/usr/bin/env node
在创建包装批处理文件时直接附加到键名称(在Unix上,按照原样为键创建符号链接);例如。:
package.json
警告:如果bin
中的.cmd
键指向的脚本具有扩展名"bin": { "foo": "./bin/fooj.js" }
,但没有shebang行< / em>,包装器脚本将直接调用bin
文件 ,默认情况下会使用WSH执行它(具体来说,使用 JScript ,它的JavaScript引擎而不是Node.js,它不会按预期工作 - 请参阅this question您将看到的症状。
答案 1 :(得分:1)
您可以告诉npm使用您的软件包提供的可执行文件可以从./node_modules/.bin
目录(在本地安装的情况下)或全局(在全局安装模块时)访问。您应该将bin
字段放入package.json
并指定脚本的相对路径。例如,jade package.json
包含以下代码:
"bin": {
"jade": "./bin/jade.js"
}
当安装jade包时,npm通过生成(如果需要的话)包装脚本(./bin/jade.js
)来使这个脚本(jade.cmd
)可访问,其内容依赖于当前的操作系统,shell和脚本的类型你希望能够访问。 Jade使用.js
脚本,npm为您的操作系统生成jade.cmd
,它将启动节点并将脚本名称作为参数传递。但是mocha-casperjs使用shell脚本,因此生成的mocha-casperjs.cmd
的内容不同 - 它启动sh.exe
而不是节点。
您可以在此处阅读bin
package.json
字段:https://docs.npmjs.com/files/package.json#bin