NPM package.json 中的 scripts 详细解读
npm 如何处理 “scripts” 字段
说明
对于以下脚本,npm 支持 package.json 文件的"scripts"属性:
- prepublish:在打包和发布该软件包之前运行,也可以在 npm install 没有任何参数的情况下在本地运行。(见下文)
- prepare:在打包和发布该软件包之前,在 npm install 没有任何参数的情况下在本地以及安装 git 依赖项时均运行这两种方法(请参见下文)。这是在之后 prepublish 但之前执行的 prepublishOnly。
- prepublishOnly:仅在打包和打包之前运行 npm publish。(见下文。)
- prepack: 前运行压缩包包装(上 npm pack,npm publish 并安装 git 的依赖时)
- postpack: 在生成 tar 包并将其移至最终目的地后运行。
- publish, postpublish: 在发布包之后运行。
- preinstall:在安装软件包之前运行
- install, postinstall:在安装软件包后运行。
- preuninstall, uninstall:在卸载软件包之前运行。
- postuninstall:卸载软件包后运行。
- preversion:在提高软件包版本之前运行。
- version:在提高软件包版本之后运行,但在提交之前。
- postversion: 运行后升级软件包版本,然后执行提交。
- pretest,test,posttest: 由 npm test 命令运行。
- prestop,stop,poststop: 由 npm stop 命令运行。
- prestart,start,poststart: 由 npm start 命令运行。
- prerestart,restart,postrestart:由 npm restart 命令运行。注意:npm restart 如果未 restart 提供脚本,将运行停止和启动脚本。
- preshrinkwrap,shrinkwrap,postshrinkwrap:由 npm shrinkwrap 命令运行。
此外,可以通过运行来执行任意脚本npm run-script <stage>
。前置和后名称匹配的命令将这些运行以及(例如 premyscript,myscript, postmyscript)。来自依赖项的脚本可以使用运行 npm explore <pkg> -- npm run <stage>
。
准备和准备
弃用说明
自以来npm@1.1.71
,npm CLI prepublish 为 npm publish 和都运行了脚本npm install
,因为这是准备要使用的软件包的便捷方法(以下部分介绍了一些常见的使用案例)。在实践中,这也令人非常困惑。从开始npm@4.0.0
,引入了一个新事件 prepare,它保留了此现有行为。已添加一个 新事件 prepublishOnly 作为过渡策略,以允许用户避免现有 npm 版本的混乱行为,而只能继续运行 npm publish(例如,最后一次运行测试以确保它们处于良好状态)。
请参阅 https://github.com/npm/npm/issues/10074 ,以获得更长时间的理由,并请继续阅读此更改。
使用案例
如果需要在使用软件包之前对软件包执行操作,而使用的方式不依赖于操作系统或目标系统的体系结构,请使用 prepublish 脚本。这包括以下任务:
-
将 CoffeeScript 源代码编译为 JavaScript。
-
创建 JavaScript 源代码的缩小版本。
-
获取您的程序包将使用的远程资源。 prepublish 一次做这些事情的好处是,它们一次可以在一个地方完成,从而降低了复杂性和可变性。此外,这意味着:
-
您可以将其 coffee-script 作为依赖 devDependency,因此您的用户不需要安装它。
-
您无需在包中包含缩小符,从而减少了用户的大小。
-
你并不需要依靠你的用户有 curl 或 wget 在目标计算机或其他系统工具。
默认值
npm 将基于包内容默认一些脚本值。
- “start”: “node server.js”:
如果 server.js 您的软件包根目录中有一个文件,那么 npm 会将 start 命令默认为 node server.js。
- “install”: “node-gyp rebuild”:
如果 binding.gyp 软件包根目录中有一个文件,而您尚未定义自己的文件 install 或 preinstall 脚本,则 npm 将默认 install 使用 node-gyp 编译该命令。
用户
如果使用 root 特权调用 npm,则它将 uid 更改为 user 配置指定的用户帐户或 uid ,默认为 nobody。设置该 unsafe-perm 标志以使用 root 特权运行脚本。
环境
程序包脚本在一个环境中运行,在该环境中,可以获得许多有关 npm 设置和进程当前状态的信息。
路径
如果您依赖于定义可执行脚本的模块(如测试套件),则这些可执行文件将添加到中 PATH 以执行脚本。因此,如果您的 package.json 具有以下内容:
{
"name" : "foo",
"dependencies" : { "bar" : "0.1.x" },
"scripts": { "start" : "bar ./test" }
}
那么您可以运行npm start
执行 bar 脚本,该脚本将导出到上的node_modules/.bin
目录中npm install
。
package.json 变量
package.json 字段添加到 npmpackage前缀。因此,例如,如果您{"name":"foo", "version":"1.2.5"}
在package.json
文件中,则您的程序包脚本会将 npm_package_name 环境变量设置为“ foo”,并将其 npm_package_version
设置为“ 1.2.5”。您可以使用process.env.npm_package_name
和 在代码中访问这些变量process.env.npm_package_version
,以此类推。
配置
配置参数放在带有 npm_config_
前缀的环境中 。例如,您可以 root 通过检查 npm_config_root
环境变量来查看有效的配置。
特殊:package.json “config"对象
如果配置参数为,则 package.json“ config”键在环境中将被覆盖<name>[@<version>]:<key>
。例如,如果 package.json 具有以下内容:
{
"name" : "foo",
"config" : { "port" : "8080" },
"scripts" : { "start" : "node server.js" }
}
而 server.js 是这样的:
http.createServer(...).listen(process.env.npm_package_config_port)
那么用户可以通过以下方式更改行为:
npm config set foo:port 80
当前生命周期事件
最后,将 npm_lifecycle_event 环境变量设置为执行循环的任何阶段。因此,您可以将一个脚本用于流程的不同部分,并根据当前情况进行切换。
对象按照这种格式展平,因此,如果您 {"scripts":{"install":"foo.js"}}
在package.json
中,则可以在脚本中看到它:
process.env.npm_package_scripts_install === "foo.js"
例子
例如,如果您的 package.json 包含以下内容:
{ "scripts" :
{ "install" : "scripts/install.js"
, "postinstall" : "scripts/install.js"
, "uninstall" : "scripts/uninstall.js"
}
}
然后scripts/install.js
在生命周期的安装和安装后阶段scripts/uninstall.js
将被调用,并且在卸载软件包时将被调用。由于 scripts/install.js
正在运行两个不同的阶段,因此在这种情况下,查看 npm_lifecycle_event 环境变量是明智的。
如果要运行 make 命令,可以这样做。这很好用:
{ "scripts" :
{ "preinstall" : "./configure"
, "install" : "make && make install"
, "test" : "make test"
}
}
退出
通过将行作为脚本参数传递给来运行脚本 sh。
如果脚本以非 0 的代码退出,则将中止该过程。
请注意,这些脚本文件不必是 nodejs 甚至是 javascript 程序。它们只是必须是某种可执行文件。
挂钩脚本
如果要在所有包的特定生命周期事件中运行特定脚本,则可以使用挂钩脚本。
将可执行文件放在处node_modules/.hooks/{eventname}
,当该软件包在根目录中安装的所有软件包的生命周期中都经过该点时,它将为所有软件包运行。
挂钩脚本的运行方式与package.json
脚本完全相同。也就是说,它们处于上述 env 的单独子进程中。
最佳做法
- 除非您确实如此,否则不要以非零错误代码退出。除卸载脚本外,这将导致 npm 操作失败,并有可能被回滚。如果故障很小,或者只会阻止某些可选功能,那么最好打印警告并成功退出。
- 尽量不要使用脚本来执行 npm 可以为您做的事情。通读 package.json 以了解您可以通过简单地适当描述软件包来指定和启用的所有内容。通常,这将导致更健壮和一致的状态。
- 检查环境以确定放置物品的位置。例如,如果 npm_config_binroot 环境变量设置为/home/user/bin,则不要尝试将可执行文件安装到中/usr/local/bin。用户可能出于某种原因以这种方式进行设置。
- 不要在脚本命令前加上“ sudo”前缀。如果出于某种原因需要 root 权限,则它将因该错误而失败,并且用户将对有问题的 npm 命令进行 sudo。
- 不要使用 install。使用.gyp 文件进行编译以及 prepublish 其他操作。您几乎永远不必显式设置预安装或安装脚本。如果执行此操作,请考虑是否还有其他选择。install 或 preinstall 脚本的唯一有效用途是用于编译,必须在目标体系结构上进行编译。