从npm script到node调试

npm script

初体验

package.json

1
2
3
4
5
6
7
{
...
"scripts": {
"serve": "node build.js"
}
...
}

命令行下使用npm run命令,就可以执行这段脚本。

1
2
3
$ npm run serve
# 等同于
$ node build.js

是什么

package.json 文件里面,使用 script 字段定义脚本命令。它有以下优点:

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

查看当前项目的所有 npm 脚本命令,可以使用不带任何参数的npm run命令。

1
$ npm run

官方用法详见

官方:脚本从包文件夹的根目录运行,无论npm调用时当前工作目录是什么。如果您希望您的脚本根据您所在的子目录使用不同的行为,您可以使用INIT_CWD环境变量,它包含您运行时所在的完整路径npm run

解读:INIT_CWD 好比变量 NODE_ENV,获取它的值局限于运行时所在的完整路径的文件,不能在该运行时的脚本引入的模块中使用,要想在模块当中直接使用,我们还需要一些配置

  • webpack4 之前可以使用DefinePlugin插件配置
  • webpack4 版本之后可以通过 mode 选项实现

原理

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

除了 Shell 预先存在的PATHnpm run添加 node_modules/.binPATH提供的脚本中。本地安装的依赖项提供的任何二进制文件都可以在没有node_modules/.bin 前缀的情况下使用。例如,如果你的包中有一个devDependencyon tap,你应该写:

1
"scripts": {"test": "tap test/\*.js"}

而不用写成下面这样。

1
"scripts": {"test": "node_modules/.bin/tap test/\*.js"}

npm 脚本执行顺序

如果 npm 脚本里面需要执行多个任务,那么需要明确它们的执行顺序。

  • 并行执行,可以使用&符号。

    1
    $ npm run script1.js & npm run script2.js

    而的 package.json 中的 script 写法。

    1
    "scripts": {"test": "script1.js & script2.js"}
  • 继发执行(即只有前一个任务成功,才执行下一个任务),可以使用&&符号。

    1
    "scripts": {"test": "script1.js && script2.js"}

npm 脚本传入参数

要使用--标明

node 调试

Node.js 包含了一个命令行的调试实用工具。 Node.js 调试器客户端不是功能齐全的调试器,但可以进行简单的步进和检查。要使用它,则使用 inspect 参数启动 Node.js,后跟要调试的脚本的路径。

node + vscode 调试

标记 debugger 位置,然后借助 vscode 的调试工具即可实现。官方用法详见

node + chrome://inspect 调试

V8 检查器集成允许将 Chrome 开发者工具绑定到 Node.js 实例以进行调试和分析。

V8 检查器可以通过在启动 Node.js 应用程序时传入 --inspect 标志来启用。 也可以使用该标志提供自定义的端口,例如 --inspect=9222 将接受端口 9222 上的开发者工具连接。

要中断应用程序代码的第一行,则传入 --inspect-brk 标志而不是 --inspect

1
2
3
$ node --inspect-brk index.js
Debugger listening on ws://127.0.0.1:9229/dc9010dd-f8b8-4ac5-a510-c1a114ec7d29
For help, see: https://nodejs.org/en/docs/inspector

从 npm script 到 node 调试

在实际开发调试过程中,我们有这样一个需求,nodejs 环境下使用 package.json 脚本设置项目环境变量,这时我们会使用 process.env.NODE_ENV (NODE_ENV 是变量名)进行获取当前的环境变量进行区分不同的运行环境。

1
2
3
4
5
6
7
8
9
{
...
"scripts": {
...
"dev": "NODE_ENV=development webpack-dev-server --inline --progress --config build/webpack.dev.conf.js --host 0.0.0.0"
...
}
...
}

编辑完脚本以后当使用脚本的时候发现没有生效,这是因为 windows 不支持直接设置 NODE_ENV=development的方式。

tips

当您使用这样 package.json 中的 scripts 来设置环境变量时,大多数 Windows 命令提示符都会阻塞 NODE_ENV=development。(例外是Bash on Windows,它使用本机 Bash。)同样,windows 和 POSIX 命令使用环境变量的方式也有所不同。在 POSIX 中,您使用:$ENV_VAR ,在 Windows 上,您使用%ENV_VAR%

NODE_ENV=development在 windows 环境下会报错,需要改为set NODE_ENV=development,而 Mac 环境的方式是 export NODE_ENV=development 。为了解决这个差异,可以使用cross-env跨平台的设置和使用环境变量。

cross-env使您可以拥有一个命令,而无需担心为平台正确设置或使用环境变量。就像在 POSIX 系统上运行时一样设置它,并且cross-env会正确设置它。官方用法详见

1
$ npm add -D cross-env

对应的 package.json script 配置如下:

1
2
3
4
5
6
7
8
9
{
...
"scripts": {
...
"dev": "cross-env NODE_ENV=development webpack-dev-server --inline --progress --config build/webpack.dev.conf.js --host 0.0.0.0"
...
}
...
}

接着,我们来分析一下上面的 package.json 片段:

cross-env NODE_ENV=development webpack-dev-server --inline --progress --config build/webpack.dev.conf.js --host 0.0.0.0

  1. 环境变量 NODE_ENV 赋值为 development,以便运行时的 webpack.dev.conf.js 下,可以通过 process.env.NODE_ENV 访问值
  2. 执行 webpack-dev-server 命令,它带有–inline, –progress , –config ,–host 四个参数,进而执行 build/webpack.dev.conf.js

使用 cross-env,webpack-dev-server 这 2 个命令,需要提前安装好开发依赖包。

1
$ npm add -D cross-env webpack-dev-server

cross-env 的用法,上文有提到,webpack-dev-server官方用法详见

相关链接

[1] npm scripts 使用指南

[2] node - debugger 调试器