简述:
在Windows上,npm
根据脚本文件中指定的 shebang 行所使用的shell/解释器来创建包装批处理文件(*.cmd)。
你所看到的是npm对于Windows操作系统的
Unixshebang机制的模拟。如果一个可执行的纯文本文件(脚本)的第一行以字符
#!
开头,那么它告诉操作系统应该将脚本传递给哪个解释器/ shell来执行(有关更多信息,请参见我的
this answer)。
由于Windows不支持shebang行,
npm
创建了一个
wrapper*.cmd
(批处理)文件,显式地调用“binary”文件(在
package.json
文件的
bin
键中指定的脚本文件),并使用脚本文件的shebang行中指定的任何可执行文件。
换句话说:
npm
解析脚本的shebang行,以确定要调用哪个shell/解释器,并相应地创建包装批处理脚本。
如果我们查看
jade
包中的
./bin/jade.js
,我们会看到
#!/usr/bin/env node
作为shebang行,这就是为什么
jade.cmd
包装文件调用
node.exe
的原因。
这是
典型情况:一个
用JavaScript编写的脚本必须由
Node.js引擎执行。
然而,
也可以指定任何其他shell/解释器,但只有在
Windows上也可用给定的shell/解释器时才有意义;对于
node
来说,这是一个确定的事实,但正如
mocha-casper.js
包中的
mocha-casper.cmd
的内容所示,使用
Unix默认shell/bin/sh
没有意义(
./bin/mocha-casperjs
文件包含shebang行
#!/bin/sh
)。
制作人选择自行开发Windows集成,通过重新实现Unix shell脚本为cmd.exe的mocha-casperjs.bat(也是批处理文件) - 然而,由于npm不知道这一点,因此该批处理文件没有放置在PATH(全局)/无法仅通过名称发现(在项目上下文中调用CLIs)。
更普遍地说,为了让脚本在Windows上也能工作,使用带有绝对的POSIX风格路径的shebang行是没有意义的,除非目标shell/解释器通过/usr/bin/env的间接调用进行指定,这会向npm发出信号,让它在PATH中查找它(请参见我的答案
this answer以获取更多信息)。另外,包装批处理文件也会在它们自己的目录中查找可执行文件,但这很少有帮助,因为即使您将它们明确添加为package.json的bin键中的条目,npm也不会将它们复制到那里。
另外一件事:最近版本的npm还为Unix环境(特别是Cygwin和Windows上的Bash)创建无扩展名的包装脚本。
创建自己的包时,如果要将 CLI(“二进制文件”)作为 npm 包的一部分直接执行脚本并像命令行实用程序一样运行,以在 Windows 上正常工作,您必须采取以下措施:
为你的脚本添加shebang行 - 即使你只打算在Windows上运行它们。
将shebang行定义为#!/usr/bin/env <interpreter-executable-filename-without-extension>
; 通常情况下,如果你的脚本是用JavaScript编写的,并且必须使用node
执行,则使用:
#!/usr/bin/env node
在你的package.json
文件的bin
键中,定义脚本键不带扩展名。,因为当包装器批处理文件创建时(在Unix上,会创建一个名为该键的符号链接),.cmd
会直接附加到键名后面;例如:
"bin": { "foo": "./bin/fooj.js" }
注意:如果在package.json
中bin
键指向的脚本具有扩展名.js
,但没有shebang行,则包装器脚本将直接调用.js
文件,这将默认使用WSH(具体来说,使用其JavaScript引擎JScript)而不是Node.js来执行,这不会按预期工作 - 参见this question以了解你将看到的症状。