最近这段时间一直在折腾各种Node CLI,把个人的一些开发,调试技巧分享给大家~
一般情况下,一套CLI工具集合,包括CLI运行核心模块及各种插件体系。拿 webpack
来说,其由核心模块 webpack
及各种 loader
plugin
组成其强大的构建生态体系。
单一NPM包的调试
npm link 到本地进行开发调试
- 先进入模块目录执行
npm link
- 再去项目目录通过包名来
link npm link my-plugin
- 删除link:
npm unlink my-plugin
npm link 的原理其实就是建立软连接,省去了自己建立软链的麻烦了
单一的npm包,调试方法比较多,vscode node-debug 或者 chrome devtool 调试node 都可以。如果是vscode ,launch.json 里面可以配置 env 与 args 也比较方便。单一模块开发推荐这种方式。
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${workspaceRoot}/bin/def.js",
"args": [
"-v"
],
"env": {
"DEF_CORE_PATH": "/Users/younth/node-cli/def/node-cli"
}
}
入口CLI的开发调试
入口cli模块一般是在 package.json
里面申明的:
"bin": {
"webpack": "./bin/webpack.js"
}
bin
字段主要用于npm i -g
时候可以将脚本添加到可执行路径中,之后可以在命令行中直接执行。例如npm i -g webpack
后就可以全局使用webpack命令。
同样的我们在 CLI 的项目目录下执行 npm link
将 webpack 放入全局,这样后面我们就可以在命令行中直接使用了。对于CLI模块的调试仍然可以使用单一模块调试方法。
但是当 webpack 再去调用 loader 或者 plugin 的时候,我们想完整的调试整个过程,就不太方便了。尝试过用 node --debug
去启动 CLI 下面的 bin/webpack
,然后在调试具体执行模块,感觉开发起来很别扭,体验不好。而且如果是模块是通过child\_process.spawn
执行的,那真就没啥办法了。最终选择了以日志的形式进行开发调试。
说起日志,最简单的就是 console.log
调试了,但问题也很明显:
- 模块本身需要输出一些信息,需要做到debug信息在正常启动模式下是不显示的
- 涉及模块越来越多的时候,
console
输出的信息会多而乱。这样增加了调试的复杂度,迫切需要 进行分模块块打印日志调试
我们引入了 debug 模块。使用也非常方便,通常我们只需要给每个模块指定特定的__命名空间__即可:
// app.js
var debug = require('debug')('app');
// 运行 DEBUG=app node app.js
// 输出:app hello
debug('hello');
debug('this is %s', string);
debug('this is %o', obj);
使用的时候,可以传参,自定义格式:
- %s: string
- %o: object
debug
同时支持命名空间:
DEBUG=app,api
:表示同时打印出命名空间为app、api的调试日志。DEBUG=a\*
:支持通配符,所有命名空间为a开头的调试日志都打印出来。
关于守护程序(daemon)模块的调试
在开发Node Cli的过程中,我们经常需要执行一些 后台程序
, 比如 检测CLI及模块的版本更新情况,其本质就是利用 child\_process.spawn
以守护进程的方式执行一个js文件。我们可以通过设定 spawn
的 stdout
参数来将输出指向某个文件。
const fs = require('fs-extra');
let stdout = fs.openSync(path.join(__dirname, 'check_out.log'), 'w')
let stderr = fs.openSync(path.join(__dirname, 'check_error.log'), 'w')
const p = child_process.spawn(
'node', ['check.js', 'a', 'b'],
{
'stdio': ['ignore', stdout, stderr],
'detached': true // 让子进程能在父进程退出后继续运行
}
);
如上述代码所示,在 check.js
里面进行 console.log
或者 debug
的,将会在 check\_out.log
里面看到结果。
正式环境的日志显示
以上都是开发时候的调试,在发布之后,有时候我们也需要一些信息输出给用户。我们经常用 --verbose
查看详细的运行情况。对于正式环境的错误提示,信息输出等,我们把日志级别分为:
- verbose:详细日志,一般是通过
--verbose
参数查看 - info:日常的输出
- warn:警告日志
- error:错误日志
- debug: 这里不需要了,因为debug已经单独拿出来用 debug模块进行输出
可以考虑用原生util模块,这里推荐使用 npmlog ,功能也比较完善。
// additional stuff ---------------------------+
// message ----------+ |
// prefix ----+ | |
// level -+ | | |
// v v v v
log.info('[core]', 'node version is : %j', nodeVersion)
其他小技巧
有时候我们也想让自己的CLI输出各种酷炫的效果,这里也把自己使用的模块分享给大家:
- CLI各种颜色输出:colors 、chalk
- CLI输出表格:cli-table easy-table
- CLI emoji 输出:node-emoji
- 持续更新...
最近也在梳理前端工程化的全链路开发的解决方案,看了业界很多工具,慢慢融化贯通后再尝试分享。