Node-js 項目調試指南
大家好,我是 ConardLi。
Node.js
是一種流行的 JavaScript
運行時,與谷歌 Chrome
瀏覽器使用相同的 V8 引擎。它是跨平臺的,在創建 Web 服務器、構建工具、命令行工具等方面越來越受歡迎。
但是,在我們編寫代碼並運行它之後,如果出現問題,事情就不會那麼清楚了。如果幸運的話,你的代碼可能會崩潰並顯示一條明顯的錯誤消息。如果你不走運,你的應用程序還是能運行的,但是最後的結果就不盡人意了。
什麼是調試?
調試是修復軟件 Bug
的藝術。修復 Bug
通常很簡單,更正一個字符或編輯一段代碼就可能解決了問題。但是找到 Bug
的原因就是另一回事來,開發人員通常會花費非常多的時間來查找問題的根源。
有一些方法可以儘可能的避免 Bug
:
-
使用具有行號、顏色編碼、lint、自動補全、括號匹配、參數提示等功能的優秀代碼編輯器。
-
使用
Git
等源代碼控制系統來管理代碼修訂。這些工具可以幫助其他人檢查更新並定位錯誤出現的方式、時間和位置。 -
採用
Bug
跟蹤系統,例如Jira、FogBugz
或Bugzilla
。使用這些報告Bug
、突出重複、記錄重現的步驟、確定嚴重性、計算優先級、分配開發人員、記錄討論和跟蹤修復進度。 -
使用測試驅動開發的模式,
TDD
是一種開發模式,它鼓勵開發人員在編寫代碼之前先編寫代碼來測試函數的運行情況。 -
嘗試使用代碼解釋或結對編程等技術與其他開發人員合作,新的眼光可能會發現你沒有考慮過的問題。
沒有任何解決方案可以根除所有的 Bug
,我們可能會在在所有的編程語言中遇到以下類型。
語法錯誤
當你的代碼沒有遵循語言的規則時,就會導致錯誤。通常,它可能是語句拼寫錯誤或缺少括號。
VS Code
等優秀的代碼編輯器有助於在我們嘗試運行 Node.js
之前發現常見的 Node.js
問題:
-
顏色編碼有效和無效的描述
-
自動補全函數和變量名
-
突出顯示匹配的括號
-
自動縮進代碼塊
-
函數、屬性和方法的參數提示
-
檢測無法訪問的代碼
-
重構凌亂的函數
你還可以使用 ESLint
等代碼檢查器來發現其他語法問題或與正常編碼風格的偏差。使用以下命令將 ESLint
安裝爲全局 Node.js
模塊:
npm i eslint -g
然後從命令行檢查 JavaScript
文件:
eslint code.js
使用 ESLint for VS Code extension
會更容易,它會在你編碼時驗證代碼:
邏輯錯誤
邏輯錯誤意味着你的代碼可以正常運行但沒有按預期工作。例如,用戶無法使用有效的憑據登錄;報告顯示不正確的統計信息,用戶數據未保存到數據庫等。原因可能是任何原因:
-
使用不正確的變量名
-
使用不正確的條件,例如
if (x > 5)
而不是if (x < 5)
-
無效的函數、參數或算法
通常需要單步執行代碼並檢查執行期間特定點的狀態。
運行時錯誤
當應用程序執行時,運行時錯誤變得很明顯。它可能不會發生並且可能是由無效的用戶輸入引起的,例如
-
試圖將一個值除以零
-
訪問不再存在的數組項或數據庫記錄
-
試圖在沒有適當訪問權限的情況下寫入文件
-
不正確的異步函數實現導致 “內存溢出” 崩潰。
衆所周知,運行時錯誤最難以復現,因此良好的日誌記錄必不可少。
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
其他選項包括:
-
--enable-source-maps
:在使用TypeScript
等轉譯器時啓用 SourceMap -
--throw-deprecation
: 使用不推薦使用的功能時拋出錯誤 -
--inspect
:激活 V8 Inspector(請參閱下面的Node.js V8 Inspector
部分)。
使用控制檯日誌記錄進行調試
調試應用程序最簡單的方法就是在執行期間將值輸出到控制檯:
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
來查看命令列表:
-
cont
或者 c:繼續執行 -
next
或者 n:運行下一個命令 -
step
或 s: 進入一個被調用的函數 -
outor
: 跳出一個被調用的函數並返回它的調用者 -
pause
: 暫停運行代碼
您還可以:
-
使用
watch ('x')
查看變量值 -
使用
setBreakpoint()/sb()
命令設置斷點 (或者你也可以插入debugger;
語句) -
重新啓動腳本
-
.exit
退出調試器
這聽起來確實有點笨拙,不過在沒有其他選擇或者你想自虐的話,可以嘗試使用下內置的調試客戶端。
使用 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
語句,這些語句在調試器運行時也會停止處理。
右側面板提供以下內容:
-
一個
Watch
面板,你可以在其中通過單擊 + 圖標並輸入其名稱來監視變量 -
Breakpoints
面板,你可以在其中查看、啓用或禁用斷點 -
Scope
面板,你可以在其中檢查所有變量 -
Call Stack
面板,你可以在其中查看爲達到這一斷點而調用的函數。
在 Paused on breakpoint
消息上方出現一行圖標。
從左到右,這些圖標執行以下操作:
-
resume execution
: 繼續處理到下一個斷點 -
step over
: 執行下一個命令但停留在當前函數內,不要跳入它調用的任何函數 -
step into
:執行下一個命令並跳轉到它調用的任何函數 -
step out
: 繼續處理到函數結束,返回調用命令 -
step
: 類似於step into
,只是它不會跳轉到async
函數中 -
停用所有斷點
-
pause on exceptions
:每當發生錯誤時停止處理。
在 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 stack
和 Breakpoints
面板的 Chrome DevTools
。Loaded Scripts
面板顯示應用程序加載的腳本,可能也包括 Node.js
內部的腳本。下面是一些工具欄的操作:
-
resume execution
: 繼續處理到下一個斷點 -
step over
: 執行下一個命令但停留在當前函數內,不要跳入它調用的任何函數 -
step into
:執行下一個命令並跳轉到它調用的任何函數 -
step out
: 繼續處理到函數結束,返回調用命令 -
重新啓動應用程序和調試器
-
停止應用程序和調試器
-
一個標準的斷點。
-
一個條件斷點,讓程序在指定條件下停止,例如
x > 3
. -
計算花括號中表達式的日誌點,例如
URL: { req.url }
其他的詳細信息,可以查看這篇文章: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
可以:
-
啓動一個
Node.js
進程本身,或者 -
附加到調試
Web Socket
服務器,可能在遠程機器或Docker
容器上運行。
上面的屏幕截圖顯示了 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
應用程序,但下面的擴展可以讓調試變得更簡單:
-
Remote - Containers
:連接運行在Docker
容器中的應用程序 -
Remote - SSH
:連接到遠程服務器上運行的應用程序 -
Remote - WSL
:通過Windows
上的WSL
連接Linux
上運行的應用程序
最後
大家還有什麼 Node.js
項目的調試技巧,可以在留言區分享出來~
本文譯自:https://blog.openreplay.com/an-introduction-to-debugging-in-nodejs
參考:
-
https://code.visualstudio.com/docs/editor/debugging#_launch-configurations
-
https://github.com/ibm/report-toolkit
-
https://nodejs.org/en/docs/guides/debugging-getting-started/
-
https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-wsl
-
https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-ssh
-
https://code.visualstudio.com/docs/introvideos/debugging
-
https://nodejs.org/api/debugger.html#debugger_breakpoints
-
https://nodejs.org/api/debugger.html
-
https://blog.openreplay.com/an-introduction-to-debugging-in-nodejs/#debugging-nodejs-apps-with-chrome
-
https://nodejs.org/api/cli.html#environment-variables
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/KIYLzDlkBZgmzpFTL25LGA