节点js中的node_modules/.bin/package.cmd文件

pra*_*hat 3 node.js npm npm-install

我是节点 js 的新手。我正在尝试构建一个 npm 模块,并将 /node_modules/.bin 文件夹中的 cmd 文件与本地包的名称混淆。

我安装了多个包作为依赖,发现cmd文件不一样。

玉石.cmd

@IF EXIST "%~dp0\node.exe" (
  "%~dp0\node.exe"  "%~dp0\..\jade\bin\jade" %*
) ELSE (
  @SETLOCAL
  @SET PATHEXT=%PATHEXT:;.JS;=;%
  node  "%~dp0\..\jade\bin\jade" %*
)
Run Code Online (Sandbox Code Playgroud)

mocha-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" %*
)
Run Code Online (Sandbox Code Playgroud)

我的问题是,如果它是由 NPM 自动生成的,为什么 npm 会为 2 个不同的包创建 2 个不同的文件。是用户创建并告诉 NPM 的东西吗?

mkl*_*nt0 5

tl;博士

在 Windows 上,根据在脚本文件的shebang 行中指定的任何外壳程序/解释npm器创建包装批处理文件 ( *.cmd) 。


你看到的是npm对WindowsUnix shebang机制的模拟,其中可执行纯文本文件(脚本)的第一行,如果它以魔术字符开头#!,告诉操作系统什么解释器/shell 传递脚本执行(有关更多信息,请参阅我的这个答案)。

由于 Windows 不支持 shebang 行,因此npm创建了一个包装 *.cmd(批处理)文件,该文件使用脚本文件的 shebang 行中指定的任何可执行文件显式调用“二进制”文件(在 的bin键中package.json指定的脚本文件)。

换句话说:npm解析脚本的 shebang 行以确定要调用的 shell/解释器,并相应地创建包装器批处理脚本。

如果我们查看包./bin/jade.js内部jade,我们会看到#!/usr/bin/env nodeshebang 行,这就是jade.cmd包装文件调用node.exe.
这是典型的情况用 JavaScript 编写脚本必须由 Node.js 引擎执行

但是,也可以指定任何其他 shell/解释器,但只有在Windows上也可以使用给定的 shell/解释器时,这样做才有意义;for node,这是一个给定的,但是,正如mocha-casper.cmd显示的内容,它对Unix 默认 shell没有意义,/bin/sh./bin/mocha-casperjsmocha-casper.js中的文件包含 shebang line #!/bin/sh)。

的制造商mocha-casperjs选择通过为as (也是一个批处理文件)重新实现Unix shell 脚本来推出自己的 Windows 集成- 然而,由于不知道这一点,这个批处理文件没有放在 PATH(全局)/不能仅通过名称发现(在项目上下文中调用 CLI 时)。cmd.exemocha-casperjs.batnpm

更一般地,对于脚本在Windows上也工作,它没有意义的使用家当用线条绝对的,POSIX风格的路径- EXCEPT如果被指定的目标壳/解释器间接调用通过/usr/bin/env,其中的信号npm,它应该是在 PATH 中寻找(再次,请参阅我的这个答案以获取更多信息)。
(此外,包装器批处理文件还会在它们自己的目录中查找可执行文件,但这很少有帮助,因为npm即使您将它们明确添加为package.json'sbin键中的条目,也不会将它们复制到那里。)

顺便说一句:最近的版本npm 为 Unix 环境创建了无扩展的包装器脚本,特别是 Cygwin 和 Windows 上的 Ubuntu 上的 Bash。


在创建自己的包时,对于 CLI(“二进制文件”)——直接可执行的脚本,就像命令行实用程序——也是 npm 包的一部分,也可以在 Windows 上运行,你必须:

  • 向您的脚本添加一条 shebang 行- 即使您只打算在 Windows 上运行它们。

  • 将该shebang线定义为#!/usr/bin/env <interpreter-executable-filename-without-extension>; 通常 - 如果您的脚本是用 JavaScript 编写的并且必须使用node-执行:
    #!/usr/bin/env node

  • package.json文件的bin密钥中,定义不带扩展名的脚本密钥。, 因为.cmd在创建包装批处理文件时直接附加到密钥名称(在 Unix 上,按原样为密钥创建一个符号链接);例如: "bin": { "foo": "./bin/fooj.js" }

  • 警告:如果由binin 键指向的脚本package.json有扩展名.js没有 shebang 行,包装脚本将直接调用该.js文件,默认情况下,它将使用WSH(特别是使用它的 JavaScript 引擎JScript)而不是Node.js 来执行它。 js,这将无法按预期工作 - 请参阅此问题以了解您会看到的症状。


小智 1

您可以告诉 npm 使软件包提供的可执行文件可从./node_modules/.bin目录(本地安装的情况下)或全局(当模块全局安装时)访问。您应该将bin字段放入package.json并指定脚本的相对路径。例如玉石package.json包含以下代码:

\n\n
"bin": {\n  "jade": "./bin/jade.js"\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

安装jade包时,npm./bin/jade.js通过生成(如果需要)包装脚本()来访问此脚本(jade.cmd),其内容取决于当前操作系统、shell和您希望访问的脚本类型。Jade 使用.js脚本,npmjade.cmd为您的操作系统生成该脚本,该操作系统将启动节点并将脚本名称作为参数传递。但是mocha-casperjs使用shell脚本,因此生成的内容与mocha-casperjs.cmd它启动的\xe2\x80\x94sh.exe而不是node不同。

\n\n

您可以在这里阅读有关bin字段的信息: https ://docs.npmjs.com/files/package.json#binpackage.json

\n