目录
脚本
选择命令行版本:
目录
描述
¥Description
package.json
文件的 "scripts"
属性支持许多内置脚本及其预设的生命周期事件以及任意脚本。这些都可以通过运行 npm run-script <stage>
或简称 npm run <stage>
来执行。具有匹配名称的前置和后置命令也将为这些运行(例如 premyscript
、myscript
、postmyscript
)。来自依赖的脚本可以使用 npm explore <pkg> -- npm run <stage>
运行。
¥The "scripts"
property of your package.json
file supports a number of built-in scripts and their preset life cycle events as well as arbitrary scripts. These all can be executed by running npm run-script <stage>
or npm run <stage>
for short. Pre and post commands with matching names will be run for those as well (e.g. premyscript
, myscript
, postmyscript
). Scripts from dependencies can be run with npm explore <pkg> -- npm run <stage>
.
前后脚本
¥Pre & Post Scripts
要为 package.json
的 "scripts"
部分中定义的任何脚本创建 "pre" 或 "post" 脚本,只需创建另一个具有匹配名称的脚本并将 "pre" 或 "post" 添加到它们的开头。
¥To create "pre" or "post" scripts for any scripts defined in the "scripts"
section of the package.json
, simply create another script with a matching name and add "pre" or "post" to the beginning of them.
{"scripts": {"precompress": "{{ executes BEFORE the `compress` script }}","compress": "{{ run command to compress files }}","postcompress": "{{ executes AFTER `compress` script }}"}}
在此示例中,npm run compress
将按照所述执行这些脚本。
¥In this example npm run compress
would execute these scripts as described.
生命周期脚本
¥Life Cycle Scripts
有一些特殊的生命周期脚本只在某些情况下发生。除了 pre<event>
、post<event>
和 <event>
脚本之外,还会出现这些脚本。
¥There are some special life cycle scripts that happen only in certain situations. These scripts happen in addition to the pre<event>
, post<event>
, and <event>
scripts.
prepare
,prepublish
,prepublishOnly
,prepack
,postpack
,dependencies
prepare (since npm@4.0.0
)
-
在打包之前运行,即在
npm publish
和npm pack
期间¥Runs BEFORE the package is packed, i.e. during
npm publish
andnpm pack
-
在本地
npm install
上运行,不带任何参数¥Runs on local
npm install
without any arguments -
在
prepublish
之后但在prepublishOnly
之前运行¥Runs AFTER
prepublish
, but BEFOREprepublishOnly
-
注意:如果通过 git 安装的包包含
prepare
脚本,则在打包和安装包之前,将安装其dependencies
和devDependencies
,并运行准备脚本。¥NOTE: If a package being installed through git contains a
prepare
script, itsdependencies
anddevDependencies
will be installed, and the prepare script will be run, before the package is packaged and installed. -
自
npm@7
起,这些脚本在后台运行。要查看输出,请运行:--foreground-scripts
。¥As of
npm@7
these scripts run in the background. To see the output, run with:--foreground-scripts
.
prepublish (DEPRECATED)
-
在
npm publish
期间不运行,但在npm ci
和npm install
期间运行。有关更多信息,请参见下文。¥Does not run during
npm publish
, but does run duringnpm ci
andnpm install
. See below for more info.
prepublishOnly
-
在封装准备和封装之前运行,仅在
npm publish
上运行。¥Runs BEFORE the package is prepared and packed, ONLY on
npm publish
.
prepack
-
在打包 tarball 之前运行(在“
npm pack
”、“npm publish
”上以及安装 git 依赖时)。¥Runs BEFORE a tarball is packed (on "
npm pack
", "npm publish
", and when installing a git dependency). -
注意:“
npm run pack
”与“npm pack
”不同。“npm run pack
”是任意用户定义的脚本名称,其中“npm pack
”是 CLI 定义的命令。¥NOTE: "
npm run pack
" is NOT the same as "npm pack
". "npm run pack
" is an arbitrary user defined script name, where as, "npm pack
" is a CLI defined command.
postpack
-
在生成 tarball 之后但在它被移动到最终目的地之前运行(如果有的话,publish 不会在本地保存 tarball)
¥Runs AFTER the tarball has been generated but before it is moved to its final destination (if at all, publish does not save the tarball locally)
dependencies
-
如果发生更改,则在修改
node_modules
目录的任何操作之后运行。¥Runs AFTER any operations that modify the
node_modules
directory IF changes occurred. -
不在全局模式下运行
¥Does NOT run in global mode
准备和预发布
¥Prepare and Prepublish
弃用注意事项:prepublish
¥Deprecation Note: prepublish
从 npm@1.1.71
开始,npm CLI 已经为 npm publish
和 npm install
运行了 prepublish
脚本,因为它是一种方便的方式来准备一个包以供使用(一些常见的用例在下面的部分中描述)。在实践中,它也被证明是 非常混乱。从 npm@4.0.0
开始,引入了一个新事件 prepare
,它保留了这种现有行为。添加了一个新事件 prepublishOnly
作为过渡策略,以允许用户避免现有 npm 版本的混乱行为,并且只在 npm publish
上运行(例如,最后一次运行测试以确保它们处于良好状态)。
¥Since npm@1.1.71
, the npm CLI has run the prepublish
script for both npm publish
and npm install
, because it's a convenient way to prepare a package for use (some common use cases are described in the section below). It has also turned out to be, in practice, very confusing. As of npm@4.0.0
, a new event has been introduced, prepare
, that preserves this existing behavior. A new event, prepublishOnly
has been added as a transitional strategy to allow users to avoid the confusing behavior of existing npm versions and only run on npm publish
(for instance, running the tests one last time to ensure they're in good shape).
有关此更改的详细说明,请参阅 https://github.com/npm/npm/issues/10074,并进一步阅读。
¥See https://github.com/npm/npm/issues/10074 for a much lengthier justification, with further reading, for this change.
用例
¥Use Cases
如果你需要在使用之前对你的包执行操作,以不依赖于目标系统的操作系统或体系结构的方式,使用 prepublish
脚本。这包括以下任务:
¥If you need to perform operations on your package before it is used, in a way that is not dependent on the operating system or architecture of the target system, use a prepublish
script. This includes tasks such as:
-
将 CoffeeScript 源代码编译成 JavaScript。
¥Compiling CoffeeScript source code into JavaScript.
-
创建 JavaScript 源代码的缩小版本。
¥Creating minified versions of JavaScript source code.
-
获取你的包将使用的远程资源。
¥Fetching remote resources that your package will use.
在 prepublish
时间做这些事情的好处是它们可以在一个地方做一次,从而降低复杂性和可变性。此外,这意味着:
¥The advantage of doing these things at prepublish
time is that they can be done once, in a single place, thus reducing complexity and variability. Additionally, this means that:
-
你可以依赖
coffee-script
作为devDependency
,因此你的用户不需要安装它。¥You can depend on
coffee-script
as adevDependency
, and thus your users don't need to have it installed. -
你不需要在你的包中包含缩小器,从而为你的用户减少大小。
¥You don't need to include minifiers in your package, reducing the size for your users.
-
你不需要依赖你的用户在目标机器上拥有
curl
或wget
或其他系统工具。¥You don't need to rely on your users having
curl
orwget
or other system tools on the target machines.
依赖
¥Dependencies
每当 npm
命令导致 node_modules
目录发生更改时,都会运行 dependencies
脚本。它在应用更改并更新 package.json
和 package-lock.json
文件之后运行。
¥The dependencies
script is run any time an npm
command causes changes to the node_modules
directory. It is run AFTER the changes have been applied and the package.json
and package-lock.json
files have been updated.
生命周期操作顺序
¥Life Cycle Operation Order
npm cache add
prepare
npm ci
-
preinstall
-
install
-
postinstall
-
prepublish
-
preprepare
-
prepare
-
postprepare
这些都是在将模块实际安装到 node_modules
之后按顺序运行的,中间没有发生任何内部操作
¥These all run after the actual installation of modules into node_modules
, in order, with no internal actions happening in between
npm diff
prepare
npm install
这些也会在你运行 npm install -g <pkg-name>
时运行
¥These also run when you run npm install -g <pkg-name>
-
preinstall
-
install
-
postinstall
-
prepublish
-
preprepare
-
prepare
-
postprepare
如果你的包的根目录中有一个 binding.gyp
文件并且你还没有定义自己的 install
或 preinstall
脚本,npm 将默认 install
命令通过 node-gyp rebuild
使用 node-gyp 编译
¥If there is a binding.gyp
file in the root of your package and you haven't defined your own install
or preinstall
scripts, npm will default the install
command to compile using node-gyp via node-gyp rebuild
这些是从 <pkg-name>
的脚本运行的
¥These are run from the scripts of <pkg-name>
npm pack
-
prepack
-
prepare
-
postpack
npm publish
-
prepublishOnly
-
prepack
-
prepare
-
postpack
-
publish
-
postpublish
npm rebuild
-
preinstall
-
install
-
postinstall
-
prepare
prepare
仅在当前目录是符号链接时运行(例如,带有链接包)
¥prepare
is only run if the current directory is a symlink (e.g. with linked packages)
npm restart
如果定义了 restart
脚本,则运行这些事件,否则运行 stop
和 start
(如果存在),包括它们的 pre
和 post
迭代)
¥If there is a restart
script defined, these events are run, otherwise stop
and start
are both run if present, including their pre
and post
iterations)
-
prerestart
-
restart
-
postrestart
npm run <user defined>
-
pre<user-defined>
-
<user-defined>
-
post<user-defined>
npm start
-
prestart
-
start
-
poststart
如果你的包根目录中有 server.js
文件,那么 npm 将默认 start
命令为 node server.js
。在这种情况下,prestart
和 poststart
仍将运行。
¥If there is a server.js
file in the root of your package, then npm will default the start
command to node server.js
. prestart
and poststart
will still run in this case.
npm stop
-
prestop
-
stop
-
poststop
npm test
-
pretest
-
test
-
posttest
npm version
-
preversion
-
version
-
postversion
关于缺少 npm uninstall
脚本的说明
¥A Note on a lack of npm uninstall
scripts
虽然 npm v6 有 uninstall
生命周期脚本,但 npm v7 没有。删除包的原因有很多种,目前还没有明确的方法可以为脚本提供足够的上下文以使其有用。
¥While npm v6 had uninstall
lifecycle scripts, npm v7 does not. Removal of a package can happen for a wide variety of reasons, and there's no clear way to currently give the script enough context to be useful.
删除包的原因包括:
¥Reasons for a package removal include:
-
用户直接卸载了这个包
¥a user directly uninstalled this package
-
用户卸载了依赖包,因此正在卸载此依赖
¥a user uninstalled a dependant package and so this dependency is being uninstalled
-
用户卸载了一个依赖包,但另一个包也依赖于这个版本
¥a user uninstalled a dependant package but another package also depends on this version
-
此版本已作为副本与另一个版本合并
¥this version has been merged as a duplicate with another version
-
等等
¥etc.
由于缺少必要的上下文,uninstall
生命周期脚本没有实现并且无法运行。
¥Due to the lack of necessary context, uninstall
lifecycle scripts are not implemented and will not function.
用户
¥User
当 npm 以 root 身份运行时,脚本始终使用工作目录所有者的有效 uid 和 gid 运行。
¥When npm is run as root, scripts are always run with the effective uid and gid of the working directory owner.
环境
¥Environment
包脚本在一个环境中运行,其中提供了许多关于 npm 设置和进程当前状态的信息。
¥Package scripts run in an environment where many pieces of information are made available regarding the setup of npm and the current state of the process.
路径
¥path
如果你依赖于定义可执行脚本的模块,例如测试套件,那么这些可执行文件将被添加到 PATH
以执行脚本。所以,如果你的 package.json 有这个:
¥If you depend on modules that define executable scripts, like test suites, then those executables will be added to the PATH
for executing the scripts. So, if your package.json has this:
{"name": "foo","dependencies": {"bar": "0.1.x"},"scripts": {"start": "bar ./test"}}
然后你可以运行 npm start
来执行 bar
脚本,该脚本被导出到 npm install
上的 node_modules/.bin
目录中。
¥then you could run npm start
to execute the bar
script, which is exported into the node_modules/.bin
directory on npm install
.
package.json 变量
¥package.json vars
package.json 字段附加在 npm_package_
前缀上。因此,例如,如果你的 package.json 文件中有 {"name":"foo", "version":"1.2.5"}
,那么你的包脚本会将 npm_package_name
环境变量设置为 "foo",并将 npm_package_version
设置为 "1.2.5"。你可以在代码中使用 process.env.npm_package_name
和 process.env.npm_package_version
访问这些变量,其他字段以此类推。
¥The package.json fields are tacked onto the npm_package_
prefix. So, for instance, if you had {"name":"foo", "version":"1.2.5"}
in your package.json file, then your package scripts would have the npm_package_name
environment variable set to "foo", and the npm_package_version
set to "1.2.5". You can access these variables in your code with process.env.npm_package_name
and process.env.npm_package_version
, and so on for other fields.
有关包配置的更多信息,请参见 package.json
。
¥See package.json
for more on package configs.
当前生命周期事件
¥current lifecycle event
最后,将 npm_lifecycle_event
环境变量设置为正在执行的循环的任何阶段。因此,你可以将一个脚本用于流程的不同部分,根据当前发生的情况进行切换。
¥Lastly, the npm_lifecycle_event
environment variable is set to whichever stage of the cycle is being executed. So, you could have a single script used for different parts of the process which switches based on what's currently happening.
对象按照这种格式展平,所以如果你的 package.json 中有 {"scripts":{"install":"foo.js"}}
,那么你会在脚本中看到:
¥Objects are flattened following this format, so if you had {"scripts":{"install":"foo.js"}}
in your package.json, then you'd see this in the script:
process.env.npm_package_scripts_install === "foo.js"
示例
¥Examples
例如,如果你的 package.json 包含以下内容:
¥For example, if your package.json contains this:
{"scripts": {"install": "scripts/install.js","postinstall": "scripts/install.js"}}
那么 scripts/install.js
将在生命周期的安装和安装后阶段被调用。由于 scripts/install.js
运行在两个不同的阶段,在这种情况下查看 npm_lifecycle_event
环境变量是明智的。
¥then scripts/install.js
will be called for the install and post-install stages of the lifecycle. Since scripts/install.js
is running for two different phases, it would be wise in this case to look at the npm_lifecycle_event
environment variable.
如果你想运行一个 make 命令,你可以这样做。这工作得很好:
¥If you want to run a make command, you can do so. This works just fine:
{"scripts": {"preinstall": "./configure","install": "make && make install","test": "make test"}}
退出
¥Exiting
通过将该行作为脚本参数传递给 sh
来运行脚本。
¥Scripts are run by passing the line as a script argument to sh
.
如果脚本以 0 以外的代码退出,那么这将中止该过程。
¥If the script exits with a code other than 0, then this will abort the process.
请注意,这些脚本文件不必是 Node.js 甚至 JavaScript 程序。它们必须是某种可执行文件。
¥Note that these script files don't have to be Node.js or even JavaScript programs. They just have to be some kind of executable file.
最佳实践
¥Best Practices
-
不要以非零错误代码退出,除非你是认真的。如果故障很小或只会阻止某些可选功能,那么最好只打印警告并成功退出。
¥Don't exit with a non-zero error code unless you really mean it. If the failure is minor or only will prevent some optional features, then it's better to just print a warning and exit successfully.
-
尽量不要使用脚本来做 npm 可以为你做的事情。通读
package.json
以查看你可以通过适当地描述你的包来指定和启用的所有内容。一般来说,这将导致更健壮和一致的状态。¥Try not to use scripts to do what npm can do for you. Read through
package.json
to see all the things that you can specify and enable by simply describing your package appropriately. In general, this will lead to a more robust and consistent state. -
检查环境以确定将东西放在哪里。例如,如果
npm_config_binroot
环境变量设置为/home/user/bin
,则不要尝试将可执行文件安装到/usr/local/bin
中。用户可能出于某种原因这样设置它。¥Inspect the env to determine where to put things. For instance, if the
npm_config_binroot
environment variable is set to/home/user/bin
, then don't try to install executables into/usr/local/bin
. The user probably set it up that way for a reason. -
不要在脚本命令前加上 "sudo"。如果出于某种原因需要 root 权限,那么它将因该错误而失败,并且用户将 sudo 有问题的 npm 命令。
¥Don't prefix your script commands with "sudo". If root permissions are required for some reason, then it'll fail with that error, and the user will sudo the npm command in question.
-
不要使用
install
。使用.gyp
文件进行编译,使用prepare
进行其他任何操作。你几乎不必显式设置预安装或安装脚本。如果你这样做,请考虑是否有其他选择。install
或preinstall
脚本的唯一有效用途是编译必须在目标架构上完成。¥Don't use
install
. Use a.gyp
file for compilation, andprepare
for anything else. You should almost never have to explicitly set a preinstall or install script. If you are doing this, please consider if there is another option. The only valid use ofinstall
orpreinstall
scripts is for compilation which must be done on the target architecture. -
无论调用
npm
时当前工作目录是什么,脚本都从包文件夹的根目录运行。如果你希望脚本根据你所在的子目录使用不同的行为,你可以使用INIT_CWD
环境变量,它包含你在运行npm run
时所在的完整路径。¥Scripts are run from the root of the package folder, regardless of what the current working directory is when
npm
is invoked. If you want your script to use different behavior based on what subdirectory you're in, you can use theINIT_CWD
environment variable, which holds the full path you were in when you rannpm run
.
也可以看看
¥See Also