Node-js 項目調試指南

大家好,我是 ConardLi

Node.js 是一種流行的 JavaScript 運行時,與谷歌 Chrome 瀏覽器使用相同的 V8 引擎。它是跨平臺的,在創建 Web 服務器、構建工具、命令行工具等方面越來越受歡迎。

但是,在我們編寫代碼並運行它之後,如果出現問題,事情就不會那麼清楚了。如果幸運的話,你的代碼可能會崩潰並顯示一條明顯的錯誤消息。如果你不走運,你的應用程序還是能運行的,但是最後的結果就不盡人意了。

什麼是調試?

調試是修復軟件 Bug 的藝術。修復 Bug 通常很簡單,更正一個字符或編輯一段代碼就可能解決了問題。但是找到 Bug 的原因就是另一回事來,開發人員通常會花費非常多的時間來查找問題的根源。

有一些方法可以儘可能的避免 Bug

沒有任何解決方案可以根除所有的 Bug ,我們可能會在在所有的編程語言中遇到以下類型。

語法錯誤

當你的代碼沒有遵循語言的規則時,就會導致錯誤。通常,它可能是語句拼寫錯誤或缺少括號。

VS Code 等優秀的代碼編輯器有助於在我們嘗試運行 Node.js 之前發現常見的 Node.js 問題:

你還可以使用 ESLint 等代碼檢查器來發現其他語法問題或與正常編碼風格的偏差。使用以下命令將 ESLint 安裝爲全局 Node.js 模塊:

npm i eslint -g

然後從命令行檢查 JavaScript 文件:

eslint code.js

使用 ESLint for VS Code extension 會更容易,它會在你編碼時驗證代碼:

邏輯錯誤

邏輯錯誤意味着你的代碼可以正常運行但沒有按預期工作。例如,用戶無法使用有效的憑據登錄;報告顯示不正確的統計信息,用戶數據未保存到數據庫等。原因可能是任何原因:

通常需要單步執行代碼並檢查執行期間特定點的狀態。

運行時錯誤

當應用程序執行時,運行時錯誤變得很明顯。它可能不會發生並且可能是由無效的用戶輸入引起的,例如

衆所周知,運行時錯誤最難以復現,因此良好的日誌記錄必不可少。

Node.js 調試環境變量

操作系統中設置的環境變量可以控制 Node.js 應用程序的設置。最常見的,我們通常在調試時或在實時服務器上把 NODE_ENV 設置爲 development、production

你可以在 Linux/macOS 上設置環境變量:

NODE_ENV=development

Windows(傳統 DOS)命令提示符下:

set NODE_ENV=development

Windows Powershell

$env:NODE_ENV="development"

我們的應用程序可以檢測環境設置並在必要時啓用調試消息,例如:

// running in development mode?
const DEVMODE = (process.env.NODE_ENV === 'development');

if (DEVMODE) {
  console.log('application started in development mode');
}

NODE_DEBUG 使用 Node.js util.debuglog 啓用調試消息。(下面的章節會詳細講解)。

使用 Node.js 命令行選項進行調試

你可以在啓動應用程序時將命令行選項傳遞給 node 或運行時。nodemon 最有用的一個選項是 --trace-warnings,它在 promise 無法解決或拒絕時輸出堆棧跟蹤:

node --trace-warnings index.js

其他選項包括:

使用控制檯日誌記錄進行調試

調試應用程序最簡單的方法就是在執行期間將值輸出到控制檯:

console.log(`ConardLi: ${ myVariable }`);

一些開發人員聲稱你永遠不應該使用 console.log(), 因爲這樣會變更代碼,並且存在更好的調試選項。但我還是認爲控制檯打印日誌記錄是一種更快速實用的選擇,查找和修復錯誤比你使用的查找方法更重要。我們還應該考慮使用 console.log() 之外的其他方法:

console.log() 接受逗號分隔的值列表。例如:

let x = 17;
console.log('x:', x);
// x: 17

使用 ES6 解構也可以提供類似的輸出:

console.log({ x });
// { x: 123 }

util.inspect 可以格式化對象以便於閱讀,console.dir() 會爲你完成更復雜的工作:

console.dir(myObject, { depth: null, color: true });

使用 Node.js util.debuglog 進行調試

Node.js 標準 util 模塊提供了一個 debuglog 方法,它可以有條件地將日誌消息寫入 STDERR

const util = require('util');
const debuglog = util.debuglog('myapp');

debuglog('myapp debug message [%d]', 123);

當你將 NODE_DEBUG 環境變量設置爲 myapp 或通配符 (如或 my) 時,控制檯將顯示這些調試信息:

MYAPP 4321: myapp debug message [123]

使用 Node.js V8 Inspector 進行調試

Node.js 實際上是包裝了 V8 JavaScript 引擎。V8 包含自己的檢查器和調試客戶端,你可以從 inspect 參數開始(注意不要將其與下面使用 Chrome 調試 Node.js 應用程序 --inspect 中描述的標誌混淆):

node inspect index.js

調試器在第一行暫停並顯示 debug 提示:

$ node inspect index.js
< Debugger listening on ws://127.0.0.1:9229/b9b6639c-bbca-4f1d-99f9-d81928c8167c
< For help, see: https://nodejs.org/en/docs/inspector
<
connecting to 127.0.0.1:9229 ... ok
< Debugger attached.
<
Break on start in index.js:17
  2
  3 const
> 4   port = (process.argv[2] || process.env.PORT || 3000),
  5   http = require('http');
  6

我們可以輸入 help 來查看命令列表:

您還可以:

這聽起來確實有點笨拙,不過在沒有其他選擇或者你想自虐的話,可以嘗試使用下內置的調試客戶端。

使用 Chrome 調試 Node.js 應用程序

使用 --inspect 標誌啓動 Node.js V8 檢查器(nodemon 也支持這個標誌。):

node --inspect index.js

它會啓動調試器,並且偵聽 127.0.0.1:9229

Debugger listening on ws://127.0.0.1:9229/4b0c9bad-9a25-499e-94ff-87c90afda461

如果你在另一臺設備或 Docker 容器上運行 Node.js 應用程序,請確保端口 9229 可訪問並使用以下方式授予遠程訪問權限:

node --inspect=0.0.0.0:9229 index.js

您可以使用 --inspect-brk 替代 --inspect 來停止第一個語句的處理,這樣你就可以逐行執行。然後打開 Chrome 瀏覽器(或任何其他基於 Chromium 的瀏覽器)並在地址欄中輸入 chrome://inspect

幾秒鐘後,你的 Node.js 應用程序應就會顯示爲遠程目標。如果沒有找到,請選中 Discover network targets 並單擊 Configure 按鈕來添加運行應用程序的設備的 IP 地址和端口。單擊目標的檢查鏈接來啓動 DevTools,如果你使用之前使用過瀏覽器調試客戶端應用程序,這應該很熟悉。

要直接從 DevTools 加載、編輯和保存文件,請打開 Sources 看板,單擊 Add folder to workspace,選擇 Node.js 文件的位置,然後單擊 Agree。現在可以從左側窗格或按 Ctrl| 打開你應用程序的任何腳本,Cmd+P 並輸入文件名。單擊任意行號來設置斷點(顯示爲藍色標記):

斷點指定調試器可以暫停處理的位置,這允許我們可以檢查程序的狀態,包括局部和全局變量。我們可以定義任意數量的斷點或向代碼中添加 debugger 語句,這些語句在調試器運行時也會停止處理。

右側面板提供以下內容:

Paused on breakpoint 消息上方出現一行圖標。

從左到右,這些圖標執行以下操作:

在 Chrome 中設置條件斷點

假設你有一個運行 1700 次迭代的循環,但你對最後一次的狀態感興趣:

for (let i = 0; i < 1700; i++) {
  // set breakpoint here?
}

您可以右鍵單擊該行,選擇 Add conditional breakpoint,然後輸入條件,例如 :

i = 999

條件斷點將會顯示爲黃色而不是藍色。

在 Chrome 中設置日誌點

日誌點就像 console.log(),沒有代碼! 當代碼執行一行時輸出表達式,但與斷點不同的是,處理不會暫停。想要添加日誌點,只需右鍵單擊任意一行,選擇 “Add log point”,輸入表達式,例如:

'loop counter i', i

使用 VS Code 調試 Node.js 應用程序

VS Code 支持 Node.js 並具有內置的調試客戶端。在本地系統上運行 Node.js 應用程序時無需配置。打開你的啓動腳本(通常是 index.js),激活 Run and Debug 看板,單擊運行和調試 Node.js 按鈕,然後選擇 Node.js 環境,單擊任意行來激活斷點。

如果你正在運行一個 Web 應用,可以在瀏覽器中打開它,VS Code 會在遇到斷點或 debugger 語句時停止執行:

VS Code 調試類似於帶有 Variables、Watch、Call stackBreakpoints 面板的 Chrome DevToolsLoaded Scripts 面板顯示應用程序加載的腳本,可能也包括 Node.js 內部的腳本。下面是一些工具欄的操作:

其他的詳細信息,可以查看這篇文章:https://code.visualstudio.com/docs/introvideos/debugging

VS Code 高級調試配置

如果你想在另一臺設備、虛擬機上調試代碼,或者需要使用其他啓動選項(例如 nodemon

編輯器將啓動配置存儲在項目隱藏文件夾內的 launch.json 文件中。要生成文件,請單擊 “create a launch” 面板頂部的 create launch.json 文件鏈接,然後選擇 Node.js 環境。

您可以使用 add configuration 按鈕將任意數量的配置設置對象添加到 "configurations" 數組。VS Code 可以:

上面的屏幕截圖顯示了 nodemon 啓動配置。Add Configration 按鈕提供了一個 nodemon 選項,因此你應該編輯該 "program" 屬性來指向你的入口腳本 ( ${workspaceFolder}/index.js )。

保存 launch.json,然後從 “Run and Debug” 面板頂部的下拉列表中選擇 nodemon,然後單擊綠色運行圖標:

nodemon 將啓動你的應用程序,然後你就可以像以前一樣編輯代碼並設置斷點或日誌點。

要了解更多信息,請參考 https://code.visualstudio.com/docs/editor/debugging#_launch-configurations

VS Code 可以調試任何 Node.js 應用程序,但下面的擴展可以讓調試變得更簡單:

最後

大家還有什麼 Node.js 項目的調試技巧,可以在留言區分享出來~

本文譯自:https://blog.openreplay.com/an-introduction-to-debugging-in-nodejs

參考:

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/KIYLzDlkBZgmzpFTL25LGA