npm scripts 中文文档 : npm 如何处理 “scripts”

文档翻译自:https://docs.npmjs.com/misc/scripts

描述

npm 支持 package.json 中的 “scripts” 属性, 包括一下 scripts:

  • prepublish: 在包 published 之前运行。也会在不带参数的 npm install 命令前运行(查看下面)。
  • prepare: 在包 packed 并且 published 之前运行, 也会在本地不带参数的 npm install 执行时运行 (查看下面)。这在 prepublish 之后,但是在 prepublishOnly 之前运行。
  • prepublishOnly: 在包 prepared 和 packed 之前,且仅在 npm publish 上运行(查看下面)。
  • prepack: 在 tarball 打包(packed) 前运行(npm packnpm publish ,和当安装 git 依赖项)。
  • postpack: 在 tarball 生成(generated),并将其移动到其最终目标地址后运行。
  • publish, postpublish: 在包 published 之后运行。
  • preinstall: 在包 installed 之前运行。
  • install, postinstall: 在包 installed 之后运行。
  • preuninstall, uninstall: 在包 uninstalled 之前运行。
  • postuninstall: 在包 uninstalled 之后运行。
  • preversion: 在包版本改变之前执行。
  • version: 在包版本改变之后执行,但在提交之前运行。
  • postversion: 在包版本改变之后执行,但在提交之后运行。
  • pretest, test, posttest: 伴随 npm test 命令运行。
  • prestop, stop, poststop: 伴随 npm stop 命令运行。
  • prestart, start, poststart: 伴随 npm start 命令运行。
  • prerestart, restart, postrestart: 伴随 npm restart 命令运行。注意:如果没有提供 restart 脚本,npm restart 将运行停止和启动脚本。
  • preshrinkwrap, shrinkwrap, postshrinkwrap: 伴随 npm shrinkwrap 命令运行。

另外,所有的 scripts 都可以用 npm run-script <stage>? 命令运行, 以 prepost 为前缀对应名称的命令会自动运行(例如 premyscript, myscript,postmyscript ),依赖包中的 scripts 可以用 npm explore <pkg> -- npm run <stage> 来运行。

prepublish 和 prepare

废弃公告:

npm@1.1.71 开始,npm CLI 会在 npm publishnpm install 之前执行 prepublish 脚本,因为这做法便于准备 package 环境(一些常见的用例在下面描述)。但事实证明这让人非常困惑。所以在 npm@4.0.0 后,新增来一种事件 prepare 来代替上述行为。另外一种 事件 prepublishOnly 作为过度策略,让用户避免以往 npm 版本的混乱行为,且仅在 npm publish 上执行(例如,publish 前最后执行一次测试,以确保无误)。

对于这个变化,更加详细的理由请查阅 <https://github.com/npm/npm/issues/10074> 。

用例

如果你需要在使用 package 之前执行某些操作,请使用 prepublish 脚本,这种方式不依赖于目标系统的操作系统或架构,这包括以下任务:

  • 把 coffeescript 源码编译成 JavaScript
  • 压缩 JavaScript 源码
  • 获取你的 package 所需的远程资源

在publish时做这些事情的好处是,它们可以在同一处完成,从而降低复杂性和差异性。另外,这意味着:

  • 你可以依赖于 coffee-script 作为 devDependency ,但你的用户不需要安装它。
  • 你不需要在包中包含 minifiers ,以节省包大小。
  • 你的用户的机器上不需要具有 curlwget 或其他系统工具。

默认值

npm 将根据 package 的内容默认一些 script 值。

  • "start": "node server.js": 如果你的 package 根目录中有 server.js 文件,那么 npm 会将默认 start 命令为 node server.js
  • "install": "node-gyp rebuild": 如果你的 package 根目录下中有 binding.gyp ,并且没定义 installpreinstall 脚本,npm 会默认 install 命令用 node-gyp 编译。?

user 用户

如果使用 root 权限调用 npm ,那么它会将 uid 更改为 user 配置指定的 uid ,默认为 nobody 。设置 unsafe-perm 以使用 root 权限运行脚本。

环境

包脚本(package scripts)在一个环境中运行,在这个环境中可以获得许多关于 npm 的设置和进程的当前状态的信息。

path 路径

如果你依赖的模块定义了可执行 scripts ,如测试套件,那么这些可执行 scripts 将被添加到 PATH 中执行。所以,如果你的 package.json 有这样的依赖:

{
    "name": "foo",
    "dependencies": {
        "bar": "0.1.x"
    },
    "scripts": {
        "start": "bar ./test"
    }
}

然后在你运行 npm start 执行 bar script,会导进 node_modules/.bin 目录中,在你运行 npm install 时,他会被导入到 node_modules/.bin 目录。

package.json vars 变量

package.json 的属性名会拼接上 npm_package_ 前缀。例如,你的 package.json 文件中有 {"name":"foo", "version":"1.2.5"} ,那么你的包脚本(package scripts)会将 npm_package_name 环境变量设置为 “foo” ,而 npm_package_version 设置为 “1.2.5” 。

configuration 配置

使用 npm_config_ 前缀将配置参数放在环境中。例如,你可以通过检查 npm_config_root 环境变量来查看当前生效的 root 配置。

特殊情况: package.json 中的 “config” 对象

如果存在 <name>[@<version>]:<key> 的配置参数,则 package.json 中的 “config” 键将在环境中被覆盖。例如,如果 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环境变量设置为执行循环的哪个阶段。
因此,您可以使用一个单独的 script,用于根据当前正在进行的切换的不同部分。

最后,npm_lifecycle_event 环境变量是用来设置当前执行循环的哪个阶段。所以,你可以使用单个单独的 script ,根据当前正在进行的事件来切换的进程的不同部分。

对象按照这种格式变平,所以如果你的 package.json 中有 {"scripts":{"install":"foo.js"}} ,那么你会在 script 中看到这个:

process.env.npm_package_scripts_install === "foo.js"

例子

假如,你的 package.json 有如下设置:

{ "scripts" :
    { "install" : "scripts/install.js"
    , "postinstall" : "scripts/install.js"
    , "uninstall" : "scripts/uninstall.js"
    }
}

那么在生命周期的 installpostinstall 阶段将调用 scripts/install.js ,在 uninstall 阶段将会调用 scripts/uninstall.js 。由于 scripts/install.js 在两个不同的阶段都有运行,因此在这种情况下,查看 npm_lifecycle_event 变量是聪明的做法。

如果你想要运行 make 命令也没问题,这样写:

{ "scripts" :
    { "preinstall" : "./configure"
    , "install" : "make && make install"
    , "test" : "make test"
    }
}

EXITING 退出

npm 脚本是通过将该行作为脚本参数传给 sh 来运行的。

如果脚本不是以退出码 0 退出,则会中止该进程。

请注意,这些脚本文件不必是 nodejs 甚至是 javascript 程序。他们只需要一些可执行文件。

HOOK SCRIPTS

如果要为所有 package 在某生命周期事件中运行某脚本,则可以使用钩子脚本。

node_modules/.hooks/{eventname} 中放置一个可执行文件,所有装在根目录下的 package 在运行到该生命周期节点时都会执行。

Hook 脚本的运行方式与 package.json 里的脚本完全相同。也就是说,它们与上述 env 在一个单独的子进程中。

最佳实践

  • 不要以 0 以外的错误码退出,除非你 真的 想这样做。因为这将导致 npm 操作失败,并可能会回滚。如果这个错误无关紧要或只会阻断一些小功能,那么最好只是输出一个警告,让线程成功退出。
  • 尽量不要使用 npm 脚本来做 npm 本身就可以做的事情。通读 package.json(5) 文件,你可以学到所有通过简单、合适的配置来具体描述你的 package 。这通常更健壮和通用。
  • 通过检查env来决定把东西装在哪。例如,如果 npm_config_binroot 环境变量设置为 /home/user/bin,那么不要尝试将可执行文件安装到 /usr/local/bin 中。用户可能因为某种原因设置了这种方式。
  • 不要在脚本命令里加 “sudo” 前缀。如果由于某些原因需要 root 权限,否则会报错;那么用户应该考虑以 sudo 运行 npm 命令。
  • 不要使用 install 脚本。使用 .gyp 文件进行编译,其他情况则使用 prepublish 。你最好永远不要自定义 preinstall 或 install 脚本。如果你要这样做,请优先考虑是否有其他办法。installpreinstall 脚本的唯一正确使用场景是用作设置那些编译的目标目录。
赞(0) 打赏
未经允许不得转载:WEB前端开发 » npm scripts 中文文档 : npm 如何处理 “scripts”

评论 1

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
  1. #-49

    学习了

    Jooger1年前 (2017-08-28)回复

前端开发相关广告投放 更专业 更精准

联系我们

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏