Node.js是一個JavaScript執行時,基於與Google Chrome瀏覽器中使用的相同的V8引擎。它通常用於構建跨平臺的伺服器端和終端應用程式。Node.js在過去十年中變得越來越流行,因為它易於安裝、實用、速度快,並且允許客戶端Web開發人員在其他地方利用他們的技能。
但是,軟體開發仍然是一項複雜的任務,您的Node.js程式碼有時會失敗。本教程演示了各種工具來幫助除錯應用程式並找出問題的原因。
Tips:Deno是一個替代的JavaScript執行時。它與Node.js相似,但更新,它消除了一些裂縫和不一致。下面的工具和資訊通常可以應用於Deno應用程式和Node.js。
- 除錯概述
- 設定適當的Node.js環境變數
- 使用Node.js命令列選項
- 將訊息輸出到控制檯
- 使用第三方日誌系統
- 使用V8檢查器
- 使用Chrome瀏覽器除錯Node.js程式碼
- 條件斷點
- 日誌點
- 使用VS Code除錯Node.js應用程式
- VS Code高階除錯配置
- 其他Node.js除錯選項
除錯概述
“除錯”是修復軟體缺陷的各種方法的名稱。修復錯誤通常很簡單。查詢錯誤的原因可能要複雜得多,並且需要花費數小時的時間。
以下部分描述了您將遇到的三種一般型別的錯誤。
語法錯誤
您的程式碼不遵循語言規則——例如,當您省略右括號或拼寫錯誤的語句,如console.lag(x)
.
一個好的程式碼編輯器可以通過以下方式幫助發現常見問題:
- 對有效或無效語句進行顏色編碼
- 型別檢查變數
- 自動完成函式和變數名
- 突出顯示匹配的括號
- 自動縮排程式碼塊
- 檢測無法訪問的程式碼
- 重構雜亂的功能
VS Code和Atom等免費編輯器對Node.js、JavaScript和TypeScript(可轉換為JavaScript)提供了很好的支援。在儲存和測試程式碼之前,通常可以發現基本語法問題。
像ESLint這樣的程式碼linter也會報告語法錯誤、縮排錯誤和未宣告的變數。ESLint是一個Node.js工具,您可以通過以下方式全域性安裝:
npm i eslint -g
您可以使用以下命令從命令列檢查JavaScript檔案:
eslint mycode.js
…但是使用編輯器外掛更容易,例如用於VS Code的ESLint或用於Atom的 linter-eslint,它們會在您鍵入時自動驗證程式碼:
VS Code中的ESlint
邏輯錯誤
您的程式碼執行但未按預期工作。例如,使用者在請求時沒有登出;報告顯示不正確的數字;資料未完全儲存到資料庫中;等等。
邏輯錯誤可能由以下原因引起:
- 使用錯誤的變數
- 不正確的條件,例如,
if (a > 5)
而不是if (a < 5)
- 未能考慮運算子優先順序的計算,例如,
1+2*3
結果為7而不是9。
執行時(或執行)錯誤
錯誤只有在應用程式執行時才會變得明顯,這通常會導致崩潰。執行時錯誤可能由以下原因引起:
- 除以已設定為零的變數
- 試圖訪問不存在的陣列項
- 嘗試寫入只讀檔案
儘管以下開發技術可以提供幫助,但邏輯和執行時錯誤更難發現:
- 使用測試驅動開發: TTD鼓勵您在開發函式之前編寫測試,例如,當Z作為引數傳遞時,X從函式Y返回。這些測試在初始開發和後續更新期間執行,以確保程式碼繼續按預期工作。
- 使用問題跟蹤系統:沒有什麼比聲稱“您的軟體無法執行”的電子郵件更糟糕的了!問題跟蹤系統允許您記錄特定問題、記錄複製步驟、確定優先順序、分配開發人員並跟蹤修復進度。
- 使用原始碼控制:Git之類的原始碼控制系統將幫助您備份程式碼、管理修訂並確定引入錯誤的位置。線上儲存庫,包括Github和Bitbucket,為小型或開源專案提供免費空間和工具。
您仍然會遇到Node.js錯誤,但以下部分描述了定位該難以捉摸的錯誤的方法。
設定適當的Node.js環境變數
在主機作業系統中設定的環境變數可以控制Node.js應用程式和模組設定。最常見的是NODE_ENV
,通常在除錯時設定為開發,或者在實時伺服器上執行時設定為生產。在macOS或Linux上設定環境變數:
NODE_ENV=development
或在(經典)Windows命令提示符下:
set NODE_ENV=development
或Windows Powershell:
$env:NODE_ENV="development"
在流行的Express.js框架中,將NODE_ENV設定為development會禁用模板檔案快取並輸出詳細的錯誤訊息,這在除錯時可能會有所幫助。其他模組可能提供類似的功能,您可以在應用程式中新增NODE_ENV條件,例如
// running in development mode? const devMode = (process.env.NODE_ENV !== 'production'); if (devMode) { console.log('application is running in development mode'); }
您還可以使用Node的util.debuglog方法有條件地輸出錯誤訊息,例如
import { debuglog } from 'util'; const myappDebug = debuglog('myapp'); myappDebug('log something');
此應用程式僅在NODE_DEBUG設定為 myapp 或 * 或 my* 等萬用字元時才會輸出日誌訊息。
使用Node.js命令列選項
節點指令碼通常使用node後跟入口指令碼的名稱來啟動:
node app.js
您還可以設定命令列選項來控制各種執行時方面。用於除錯的有用標誌包括:
--check
語法檢查指令碼而不執行--trace-warnings
當JavaScript Promises未解析或拒絕時輸出堆疊跟蹤--enable-source-maps
使用TypeScript等轉譯器時顯示源對映--throw-deprecation
使用已棄用的Node.js功能時發出警告--redirect-warnings=file
將警告輸出到檔案而不是stderr--trace-exit
呼叫時輸出堆疊跟蹤process.exit()
。
將訊息輸出到控制檯
輸出控制檯訊息是除錯Node.js應用程式的最簡單方法之一:
console.log(`someVariable: ${ someVariable }`);
很少有開發人員意識到還有許多其他控制檯方法:
控制檯方法 | 描述 |
---|---|
.log(msg) |
標準控制檯訊息 |
.log('%j', obj) |
將物件輸出為緊湊的JSON字串 |
.dir(obj, opt) |
漂亮列印物件屬性 |
.table(obj) |
以表格格式輸出陣列和物件 |
.error(msg) |
錯誤資訊 |
.count(label) |
增加一個命名的計數器和輸出 |
.countReset(label) |
重置命名計數器 |
.group(label) |
縮排一組訊息 |
.groupEnd(label) |
終止一個組 |
.time(label) |
啟動一個命名的計時器 |
.timeLog(label) |
報告經過的時間 |
.timeEnd(label) |
停止一個命名的計時器 |
.trace() |
輸出堆疊跟蹤(所有函式呼叫的列表) |
.clear() |
清除控制檯 |
console.log()
還接受逗號分隔值的列表:
let x = 123; console.log('x:', x); // x: 123
…儘管ES6解構提供了類似的輸出,但花費更少:
console.log({ x }); // { x: 123 }
console.dir()命令以與util.inspect()相同的方式漂亮地列印物件屬性:
console.dir(myObject, { depth: null, color: true });
控制檯爭議
一些開發人員聲稱您永遠不應該使用console.log()
,因為:
- 您正在更改程式碼並且可能會更改某些內容或忘記刪除它,並且
- 當有更好的除錯選項時,就沒有必要了。
不要相信任何聲稱他們從未使用過的人console.log()
!記錄既快又髒,但每個人都在某個時候使用它。使用您喜歡的任何工具或技術。修復一個錯誤比你找到它的方法更重要。
使用第三方日誌系統
第三方日誌系統提供更復雜的功能,例如訊息傳遞級別、詳細程度、排序、檔案輸出、分析、報告等。流行的解決方案包括cabinet、loglevel、morgan、pino、signale、storyboard、tracer和winston。
使用V8檢查器
V8 JavaScript引擎提供了一個可以在Node.js中使用的除錯客戶端。使用節點檢查啟動應用程式,例如
node inspect app.js
偵錯程式在第一行暫停並顯示debug>提示:
$ node inspect .\mycode.js < Debugger listening on ws://127.0.0.1:9229/143e23fb < For help, see: https://nodejs.org/en/docs/inspector < ok < Debugger attached. < Break on start in mycode.js:1 > 1 const count = 10; 2 3 for (i = 0; i < counter; i++) { debug>
輸入幫助以檢視命令列表。您可以通過輸入以下內容逐步完成應用程式:
- cont 或 c : 繼續執行
- next 或 n:執行下一個命令
- step 或 s:進入被呼叫的函式
- out 或 o : 跳出函式並返回撥用語句
- pause:暫停正在執行的程式碼
- watch(‘myvar’) : 觀察一個變數
- setBreakPoint() 或 sb():設定斷點
- restart:重新啟動指令碼
- .exit 或 Ctrl | Cmd + D:退出偵錯程式
誠然,這種除錯選項既費時又笨拙。僅在沒有其他選項時使用它,例如當您在遠端伺服器上執行程式碼並且無法從其他地方連線或安裝其他軟體時。
使用Chrome瀏覽器除錯Node.js程式碼
上面使用的Node.js檢查選項啟動了一個Web Socket伺服器,它在localhost埠9229上進行偵聽。它還啟動了一個基於文字的除錯客戶端,但也可以使用圖形客戶端——例如內建於Google Chrome和基於Chrome的客戶端Chromium、Edge、Opera、Vivaldi和Brave等瀏覽器。
要除錯典型的Web應用程式,請使用–inspect選項啟動它以啟用V8偵錯程式的Web Socket伺服器:
node --inspect index.js
筆記:
- index.js被假定為應用程式的入口指令碼。
- 確保您使用
--inspect
雙破折號以確保您不會啟動基於文字的偵錯程式客戶端。 - 如果您想在檔案更改時自動重新啟動應用程式,您可以使用nodemon而不是node。
預設情況下,偵錯程式只接受來自本地機器的傳入連線。如果您在其他裝置、虛擬機器或Docker容器上執行應用程式,請使用:
node --inspect=0.0.0.0:9229 index.js
節點檢查選項
您還可以使用--inspect-brk
而不是--inspect
在第一行停止處理(設定斷點),以便您可以從頭開始逐步執行程式碼。
開啟基於Chrome的瀏覽器並chrome://inspect
在位址列中輸入以檢視本地和聯網裝置:
Chrome檢查工具
如果您的Node.js應用程式未顯示為Remote Target,則:
- 單擊Open dedicated DevTools for Node並選擇地址和埠,或者
- 檢查Discover network targets,單擊Configure,然後新增執行它的裝置的IP地址和埠。
單擊Target的inspect連結以啟動DevTools偵錯程式客戶端。使用DevTools進行客戶端程式碼除錯的任何人都應該熟悉這一點:
Chrome開發工具
切換到Sources面板。您可以通過點選Cmd | Ctrl + P開啟任何檔案並輸入其檔名(例如index.js)。
但是,將專案資料夾新增到工作區更容易。這允許您直接從DevTools載入、編輯和儲存檔案(您是否認為這是一個好主意是另一回事!)
- 單擊+ 將資料夾新增到工作區
- 選擇Node.js專案的位置
- 點選Agree以允許檔案更改
您現在可以從左側目錄樹載入檔案:
Chrome DevTools Sources面板
單擊任何行號以設定由藍色標記表示的斷點。
除錯基於斷點。這些指定偵錯程式應在何處暫停程式執行並顯示程式的當前狀態(變數、呼叫堆疊等)
您可以在使用者介面中定義任意數量的斷點。另一種選擇是放置一個偵錯程式;宣告到您的程式碼中,當附加偵錯程式時停止。
載入並使用您的Web應用程式到達設定斷點的語句。在此處的示例中,http://localhost:3000/在任何瀏覽器中開啟,DevTools將在第44行停止執行:
Chrome斷點
右側面板顯示:
- 一排操作圖示(見下文)。
- Watch窗格允許您通過單擊+圖示並輸入變數名稱來監視變數。
- Breakpoints窗格顯示所有斷點的列表,並允許啟用或禁用它們。
- Scope窗格顯示所有本地、模組和全域性變數的狀態。您將最常檢查此窗格。
- Call Stack窗格顯示了為達到這一點而呼叫的函式的層次結構。
Paused on breakpoint上方顯示了一排操作圖示:
Chrome斷點圖示
從左到右,它們執行以下操作:
- resume execution : 繼續處理直到下一個斷點
- step over:執行下一個命令,但停留在當前程式碼塊內——不要跳轉到它呼叫的任何函式
- step into : 執行下一個命令並根據需要跳轉到任何函式
- step out:繼續處理到函式結束,返回撥用命令
- step : 與step into類似,只是它不會跳轉到非同步函式
- deactivate所有斷點
- pause on exceptions:發生錯誤時停止處理。
條件斷點
有時有必要對斷點進行更多控制。假設您有一個完成1,000次迭代的迴圈,但您只對最後一次的狀態感興趣:
for (let i = 0; i < 1000; i++) { // set breakpoint here }
與其單擊resume execution 999次,不如右鍵單擊該行,選擇Add conditional breakpoint,然後輸入一個條件,例如i = 999
:
Chrome條件斷點
Chrome以黃色而不是藍色顯示條件斷點。在這種情況下,斷點僅在迴圈的最後一次迭代時觸發。
日誌點
日誌點無需任何程式碼即可有效實現console.log()!當程式碼執行任何一行時,可以輸出一個表示式,但它不會停止處理,這與斷點不同。
要新增日誌點,請右鍵單擊任意行,選擇Add log point,然後輸入表示式,例如'loop counter i', i
:
Chrome日誌點
DevTools控制檯輸出loop counter i: 0
到loop counter i: 999
上例中。
使用VS Code除錯Node.js應用程式
VS Code或Visual Studio Code是來自Microsoft的免費程式碼編輯器,在Web開發人員中很受歡迎。該應用程式可用於Windows、macOS和Linux,並使用Electron框架中的Web技術開發。
VS Code支援Node.js並具有內建的除錯客戶端。大多數應用程式無需任何配置即可除錯;編輯器會自動啟動除錯伺服器和客戶端。
開啟啟動檔案(例如index.js),啟用Run and Debug窗格,單擊Run and Debug按鈕,然後選擇Node.js環境。單擊任意行以啟用顯示為紅色圓圈圖示的斷點。然後,像以前一樣在瀏覽器中開啟應用程式——VS Code在到達斷點時停止執行:
VS程式碼斷點
Variables、Watch、Call Stack和Breakpoints窗格與Chrome DevTools中顯示的相似。Loaded Scripts窗格顯示已載入的指令碼,儘管許多指令碼是Node.js內部的。
操作圖示工具欄允許您:
- resume execution : 繼續處理直到下一個斷點
- step over:執行下一個命令,但停留在當前函式內——不要跳轉到它呼叫的任何函式
- step into:執行下一個命令並跳轉到它呼叫的任何函式
- step out:繼續處理到函式結束,返回撥用命令
- restart應用程式和偵錯程式
- stop應用程式和偵錯程式
與Chrome DevTools一樣,您可以右鍵單擊任意行以新增Conditional breakpoints和Log points。
有關詳細資訊,請參閱Visual Studio Code中的除錯。
VS Code高階除錯配置
如果您想在另一臺裝置、虛擬機器上除錯程式碼,或者需要使用其他啟動選項(例如nodemon),則可能需要進一步的VS Code配置。
VS Code將除錯配置儲存在專案目錄.vscode
中的launch.json檔案中。開啟Run and Debug窗格,單擊create a launch.json file,然後選擇Node.js環境來生成此檔案。提供了一個示例配置:
VS Code偵錯程式配置
可以將任意數量的配置設定定義為"configurations"
陣列中的物件。單擊Add Configuration…並選擇適當的選項。
單個Node.js配置可以:
- 啟動程序本身,或
- 附加到除錯Web Socket伺服器,可能在遠端機器或Docker容器上執行。
例如,要定義nodemon配置,請選擇Node.js: Nodemon Setup並在必要時更改“program”入口指令碼:
{ // custom configuration "version": "0.2.0", "configurations": [ { "console": "integratedTerminal", "internalConsoleOptions": "neverOpen", "name": "nodemon", "program": "${workspaceFolder}/index.js", "request": "launch", "restart": true, "runtimeExecutable": "nodemon", "skipFiles": [ "<node_internals>/**" ], "type": "pwa-node" } ] }
儲存launch.json
檔案,nodemon (配置“name”)出現在“Run and Debug”窗格頂部的下拉選單中。單擊綠色執行圖示開始使用該配置並使用nodemon啟動應用程式:
使用nodemon進行VS Code除錯
和以前一樣,您可以新增斷點、條件斷點和日誌點。主要區別在於,當檔案被修改時,nodemon會自動重啟你的伺服器。
有關詳細資訊,請參閱VS Code啟動配置。
以下VS Code擴充套件還可以幫助您除錯託管在遠端或隔離伺服器環境中的程式碼:
- Remote — Containers:連線到在Docker容器中執行的應用程式
- Remote — SSH:連線到遠端伺服器上執行的應用程式
- Remote — WSL:連線到在Linux的Windows子系統 (WSL) 上執行的應用程式。
其他Node.js除錯選項
Node.js除錯指南為一系列文字編輯器和IDE提供建議,包括Visual Studio、JetBrains WebStorm、Gitpod和Eclipse 。Atom提供了一個node-debug擴充套件,它將Chrome DevTools偵錯程式整合到編輯器中。
一旦您的應用程式上線,您可以考慮使用商業除錯服務,例如LogRocket和Sentry.io,它們可以記錄和回放真實使用者遇到的客戶端和伺服器錯誤。
小結
從歷史上看,JavaScript除錯一直很困難,但在過去十年中已經有了巨大的改進。選擇與為其他語言提供的選擇一樣好——如果不是更好的話。
使用任何實用的工具來定位問題。console.log()用於快速查詢bug沒有任何問題,但對於更復雜的問題,Chrome DevTools或VS Code可能更可取。這些工具可以幫助您建立更強大的程式碼,並且您將花費更少的時間來修復錯誤。
評論留言