代碼調試有時候是一種充滿挑戰的工作,如果有一個趁手的調試工具的話,往往可以做到事半功倍的效果。得益於這些年的快速發展,在 NodeJS 生態中已經有了多種調試工具可以使用。我們今年就來分享幾個常用的調試工具。
在 NodeJS 的代碼調試中,通常又兩大類調試方法,一種是打印日志,另一種是直接調試代碼。我們現在來分別說明。
日志
日志可以幫助我們記錄在程序運行過程中的一些狀態和錯誤信息。通過日志,我們可以快速的找到出問題的代碼。比如借助於異常日志,我們可以快速的定位到具體的代碼行。
debug 模塊
debug 是很多 NodeJS 包和框架使用的日志工具。這個包的優點是可以通過環境變量的形式細粒度的控制打印哪些日志。
比如在下面的代碼中,假設我們先發送了一些請求,然后又接受到了響應數據。
// index.js
const debugHttpIncoming = require('debug')('http:incoming')
const debugHttpOutgoing = require('debug')('http:outgoing')
let outgoingRequest = {
url: 'https://google.com'
}
// sending some request
debugHttpOutgoing('sending request to %s', outgoingRequest.url)
let incomingRequest = {
body: '{"status": "ok"}'
}
// serving some request
debugHttpOutgoing('got JSON body %s', incomingRequest.body)
當我們通過如下方式啟動程序的時候:
DEBUG=http:incoming,http:outgoing node index.js
日志展示如下:
同時,debug 模塊還支持 *
通配符,我們可以通過 DEBUG=http:* node index.js
獲得上面相同的日志輸出。
記錄日志到文件
通常,我們需要將應用運行的日志做持久化處理,最簡單的方式就是記錄到文件。
pino 是一個高性能的日志模塊,與 bunyan 類似,但是性能更好。
以下是幾種日志模塊的性能數據對比:
benchWinston*10000: 2226.117ms
benchBunyan*10000: 1355.229ms
benchDebug*10000: 445.291ms
benchLogLevel*10000: 322.181ms
benchBole*10000: 291.727ms
benchPino*10000: 269.109ms
benchPinoExtreme*10000: 102.239ms
pino 使用非常簡單:
const pino = require('pino')()
pino.info('hello pino')
pino.info('the answer is %d', 42)
pino.error(new Error('an error'))
上面的代碼,日志輸出如下:
{"level":30,"time":1632626946507,"pid":77749,"hostname":"everfind-MacBook-Pro.local","msg":"hello pino"}
{"level":30,"time":1632626946508,"pid":77749,"hostname":"everfind-MacBook-Pro.local","msg":"the answer is 42"}
{"level":50,"time":1632626946508,"pid":77749,"hostname":"everfind-MacBook-Pro.local","stack":"Error: an error\n at Object.<anonymous> (/Users/everfind/workspace/ztest/test/pino.js:5:12)\n at Module._compile (internal/modules/cjs/loader.js:1072:14)\n at Object.Module._extensions..js (internal/modules/cjs/loader.js:1101:10)\n at Module.load (internal/modules/cjs/loader.js:937:32)\n at Function.Module._load (internal/modules/cjs/loader.js:778:12)\n at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:76:12)\n at internal/main/run_main_module.js:17:47","type":"Error","msg":"an error"}
調試
NodeJS 內置調試模塊
NodeJS 提供了內置的調試模塊。使用起來非常簡單直接,缺點是沒有 UI 頁面,純命令行操作。
$ node debug index.js
我們通過 debugger
語句來設置斷點。
const express = require('express');
const app = express();
app.get('/', (req, res) => {
debugger;
res.send('ok');
});
app.listen(3000);
內置的調試模塊支持如下命令:
- cont 或 c –- 繼續執行
- next 或 n –- 往下一步
- step 或 s –- 進入函數
- out 或 o –- 退出函數
- repl –- 刷新上下文信息
V8 Inspector
我們還可以通過 V8 inspector,使用 Chrome 的 DevTools 來調試 NodeJS 代碼。
$ node --inspect index.js
上面這條命令,通過 --inspect
參數告訴 NodeJS 啟用 V8 Inspector。之后我們在 Chrome 中輸入 chrome://inspect/
,然后找到我們要調試的那個文件,就可以使用 Chrome DevTools 調試代碼了。
有時候,我們需要在代碼的入口處開始調試,則可以通過 --inspect-brk
來在起始地點開始調試。
$ node --inspect-brk index.js
VSCode
最后我們介紹如何在 VSCode 中調試代碼,這也是最高頻使用的。
通常我們可以直接通過菜單啟動調試,就像上面的演示效果那樣。
如果我們需要一些高級設置,VSCode 允許我們配置一個 .vscode/launch.json
文件,來告訴 VSCode 如何啟動調試器。
默認的配置項如下:
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${workspaceRoot}/index.js"
},
{
"type": "node",
"request": "attach",
"name": "Attach to Port",
"address": "localhost",
"port": 5858
}
]
}
關於每個配置項的作用和具體用法,可以在 VSCode 的文檔中查詢。
另外,如果我們在 VSCode 的內置命令行通過 node --inspect
啟動程序的話,會自動激活 VSCode 的調試功能。
常見面試知識點、技術解決方案、教程,都可以掃碼關注公眾號“眾里千尋”獲取,或者來這里 https://everfind.github.io 。