npm脚本

npm脚本

Node 开发离不开 npm,而脚本功能是 npm 最强大、最常用的功能之一。

什么是 npm 脚本?

  1. npm 允许在package.json文件里面使用 scripts 字段定义脚本命令。
    {
    "scripts": {
        "build": "node build.js"
    }}
  1. 上面代码是 package.json 文件的一个片段,里面的 scripts 字段是一个对象。它的每一个属性,对应一段脚本。比如,build 命令对应的脚本是 node build.js。

  2. 使用:命令行下使用npm run命令,就可以执行这段脚本。
    $ npm run build
    等同于执行
    $ node build.js

  3. 这些定义在 package.json 里面的脚本,就称为 npm 脚本。

  4. npm脚本优点:

    • 项目的相关脚本,可以集中在一个地方。
    • 外接口。用户不不同项目的脚本命令,只要功能相同,就可以有同样的,对需要知道怎么测试你的项目,只要运行npm run test即可。
    • 可以利用 npm 提供的很多辅助功能。
    • 查看当前项目的所有 npm 脚本命令,可以使用不带任何参数的npm run命令。

npm 脚本的原理

  1. 每当执行npm run,就会自动新建一个 Shell(终端),在这个 Shell 里面执行指定的脚本命令。因此,只要是 Shell(一般是 Bash)可以运行的命令,就可以写在 npm 脚本里面。

  2. 比较特别的是,npm run新建的这个 Shell,会将当前目录的 node_modules/.bin子目录 加入 PATH 变量,执行结束后,再将PATH变量恢复原样。
    这意味着,当前目录的node_modules/.bin子目录里面的所有脚本,都可以直接用脚本名调用,而不必加上路径。比如,当前项目的依赖里面有 Mocha,只要直接写 mocha test 就可以了。
    "test": "mocha test"//退出码
    而不用写成下面这样。
    "test": "./node_modules/.bin/mocha test"

  3. 由于 npm 脚本的唯一要求就是可以在 Shell 执行,因此它不一定是 Node 脚本,任何可执行文件都可以写在里面。

  4. npm 脚本也遵守 Shell 脚本规则。如果退出码不是0,npm 就认为这个脚本执行失败。

通配符

  1. 由于 npm 脚本就是 Shell 脚本,因为可以使用 Shell 通配符。
   //*表示任意文件名,**表示任意一层子目录
   "lint": "jshint *.js"

   "lint": "jshint **/*.js"
  1. 如果要将通配符传入原始命令,防止被 Shell 转义,要将星号转义。
    "test": "tap test/\*.js"

传参

  1. 向 npm 脚本传入参数,要使用–标明。
    "lint": "jshint **.js"
  1. 向上面的npm run lint命令传入参数,必须写成下面这样。
    $ npm run lint -- --reporter checkstyle > checkstyle.xml

  2. 也可以在package.json里面再封装一个命令。

   "lint": "jshint **.js","lint:checkstyle": "npm run lint -- --reporter checkstyle > checkstyle.xml"

执行顺序

  1. 如果 npm 脚本里面需要执行多个任务,那么需要明确它们的执行顺序。
    如果是并行执行(即同时的平行执行),可以使用&符号。
    $ npm run script1.js & npm run script2.js

  2. 如果是继发执行(即只有前一个任务成功,才执行下一个任务),可以使用&&符号。
    $ npm run script1.js && npm run script2.js

默认值

  1. 一般来说,npm 脚本由用户提供。但是 npm 对两个脚本提供了默认值。也就是说,这两个脚本不用定义,就可以直接使用。
   "start": "node server.js""install": "node-gyp rebuild""build": "node build.js"
  1. 上面代码中,npm run start 的默认值是node server.js,前提是项目根目录下有server.js这个脚本;
    npm run install的默认值是node-gyp rebuild,前提是项目根目录下有对应的文件。

钩子

  1. npm 脚本有 pre 和 post 两个钩子

  2. 举例来说,build脚本命令的钩子就是prebuild和postbuild。

   "prebuild": "echo I run before the build script",
   "build": "cross-env NODE_ENV=production webpack",
   "postbuild": "echo I run after the build script"
  1. 用户执行npm run build的时候,会自动按照下面的顺序执行。
    npm run prebuild && npm run build && npm run postbuild

  2. 因此,可以在这两个钩子里面,完成一些准备工作和清理工作。下面是一个例子。

   "clean": "rimraf ./dist && mkdir dist",
   "prebuild": "npm run clean",
   "build": "cross-env NODE_ENV=production webpack"
  1. npm 默认提供下面这些钩子。
    prepublish,postpublish
    preinstall,postinstall
    preuninstall,postuninstall
    preversion,postversion
    pretest,posttest
    prestop,poststop
    prestart,poststart
    prerestart,postrestart
  1. 自定义的脚本命令也可以加上 pre 和 post 钩子。
    比如,myscript这个脚本命令,也有premyscript和postmyscript钩子。
    不过,st无双重的pre和post,比如prepretest和postposttest是无效的。

  2. npm 提供一个npm_lifecycle_event变量,返回当前正在运行的脚本名称,比如pretest、test、posttest等等。所以,可以利用这个变量,在同一个脚本文件里面,为不同的npm scripts命令编写代码。请看下面的例子。

    const TARGET = process.env.npm_lifecycle_event;

    if (TARGET === 'test') {
    console.log(`Running the test task!`);}

    if (TARGET === 'pretest') {
    console.log(`Running the pretest task!`);}

    if (TARGET === 'posttest') {
    console.log(`Running the posttest task!`);}

  1. 注意,prepublish这个钩子不仅会在npm publish命令之前运行,还会在npm install(不带任何参数)命令之前运行
    这种行为很容易让用户感到困惑,所以 npm4 引入了一个新的钩子 prepare,行为等同于prepublish,
    而从 npm5 开始,prepublish将只在npm publish命令之前运行。

简写形式

  1. 四个常用的 npm 脚本有简写形式。
    npm start是npm run start
    npm stop是npm run stop的简写
    npm test是npm run test的简写
    npm restart是npm run stop && npm run restart && npm run start的简写
  1. npm startnpm stopnpm restart都比较好理解,而npm restart是一个复合命令,实际上会执行三个脚本命令。具体的执行顺序如下。
    prerestart
    prestop
    stop
    poststop
    restart
    prestart
    start
    poststart
    postrestart

变量

  1. npm 脚本有一个非常强大的功能,就是可以使用 npm 的内部变量。
    首先,通过npm_package_前缀,npm 脚本可以拿到package.json里面的字段。比如,下面是一个package.json。
    {
        "name": "foo",
        "version": "1.2.5",
        "scripts": {
        "view": "node view.js"
    }}
    //变量npm_package_name返回foo,变量npm_package_version返回1.2.5。
    
    // view.js
    console.log(process.env.npm_package_name); // foo
    console.log(process.env.npm_package_version); // 1.2.5
  1. 注意,package.json里面的config对象,可以被环境变量覆盖
    {
        "name" : "foo",
        "config" : { "port" : "8080" },
        "scripts" : { "start" : "node server.js"
    }}
  1. npm_package_config_port变量返回的是8080。这个值可以用下面的方法覆盖。
    $ npm config set foo:port 80

  2. env命令可以列出所有环境变量。
    "env": "env"

常用脚本示例

    // 删除目录
    "clean": "rimraf dist/*",
    
    // 本地搭建一个 HTTP 服务
    "serve": "http-server -p 9090 dist/",
    
    // 打开浏览器
    "open:dev": "opener http://localhost:9090",
    
    // 实时刷新
    "livereload": "live-reload --port 9091 dist/",
    
    // 构建 HTML 文件
    "build:html": "jade index.jade > dist/index.html",
    
    // 只要 CSS 文件有变动,就重新执行构建
    "watch:css": "watch 'npm run build:css' assets/styles/",
    
    // 只要 HTML 文件有变动,就重新执行构建
    "watch:html": "watch 'npm run build:html' assets/html",
    
    // 部署到 Amazon S3
    "deploy:prod": "s3-cli sync ./dist/ s3://example-com/prod-site/",
    
    // 构建 favicon
    "build:favicon": "node scripts/favicon.js",
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值