在 VS Code 中除錯 Node.js
Visual Studio Code 編輯器內建了對 Node.js 執行時的除錯支援,可以除錯 JavaScript、TypeScript 以及許多其他被轉譯成 JavaScript 的語言。使用 VS Code 設定 Node.js 專案進行除錯非常簡單,因為它提供了適當的啟動配置預設值和程式碼片段。
您可以透過以下幾種方式在 VS Code 中除錯 Node.js 程式:
- 使用自動附加除錯您在 VS Code 整合終端中執行的程序。
- 使用JavaScript 除錯終端,類似於使用整合終端。
- 使用啟動配置啟動您的程式,或附加到在 VS Code 之外啟動的程序。
自動附加
如果啟用了自動附加功能,Node 偵錯程式會自動附加到從 VS Code 整合終端啟動的某些 Node.js 程序。要啟用此功能,可以從命令面板(⇧⌘P(Windows、Linux Ctrl+Shift+P))使用切換自動附加命令,或者如果已啟用,則使用自動附加狀態列項。
自動附加有三種模式,您可以在結果快速選擇中和透過 debug.javascript.autoAttachFilter 設定選擇它們:
smart
- 如果您在node_modules
資料夾之外執行指令碼或使用常見的“runner”指令碼(如 mocha 或 ts-node),則會除錯該程序。您可以使用自動附加智慧模式設定(debug.javascript.autoAttachSmartPattern
)配置“runner”指令碼允許列表。always
- 在整合終端中啟動的所有 Node.js 程序都將被除錯。onlyWithFlag
- 僅除錯使用--inspect
或--inspect-brk
標誌啟動的程序。
啟用自動附加後,您需要透過單擊終端右上角的 ⚠ 圖示或建立一個新終端來重新啟動終端。然後,偵錯程式應該在一秒鐘內附加到您的程式。
當自動附加開啟時,自動附加
項將顯示在 VS Code 視窗底部的狀態列中。點選它可以更改自動附加模式,或暫時關閉它。如果您正在執行一些不需要除錯的一次性程式,但又不想完全停用該功能,則暫時關閉自動附加會很有用。
額外配置
其他啟動配置屬性
您可以將通常在 launch.json 中找到的其他屬性應用到 debug.javascript.terminalOptions 設定中的自動附加。例如,要將 Node 內部檔案新增到您的 skipFiles 中,您可以將以下內容新增到您的使用者或工作區設定中:
"debug.javascript.terminalOptions": {
"skipFiles": [
"<node_internals>/**"
]
},
自動附加智慧模式
在 smart
自動附加模式下,VS Code 將嘗試附加到您的程式碼,而不是附加到您不感興趣的構建工具。它透過將主指令碼與全域性模式列表進行匹配來實現此目的。全域性模式可在 debug.javascript.autoAttachSmartPattern 設定中配置,預設值為:
[
'!**/node_modules/**', // exclude scripts in node_modules folders
'**/$KNOWN_TOOLS$/**' // but include some common tools
];
$KNOWN_TOOLS$
被替換為常見“程式碼執行器”的列表,例如 ts-node
、mocha
、ava
等。如果這些設定不起作用,您可以修改此列表。例如,要排除 mocha
幷包含 my-cool-test-runner
,您可以新增兩行:
[
'!**/node_modules/**',
'**/$KNOWN_TOOLS$/**',
'!**/node_modules/mocha/**', // use "!" to exclude all scripts in "mocha" node modules
'**/node_modules/my-cool-test-runner/**' // include scripts in the custom test runner
];
JavaScript 除錯終端
與自動附加類似,JavaScript 除錯終端將自動除錯您在其中執行的任何 Node.js 程序。您可以透過從命令面板 (kbs(workbench.action.showCommands)
) 執行除錯:建立 JavaScript 除錯終端命令,或者從終端切換器下拉選單中選擇建立 JavaScript 除錯終端來建立除錯終端。
額外配置
其他啟動配置屬性
您可以將通常在 launch.json 中找到的其他屬性應用到 debug.javascript.terminalOptions 設定中的除錯終端。例如,要將 Node 內部檔案新增到您的 skipFiles 中,您可以將以下內容新增到您的使用者或工作區設定中:
"debug.javascript.terminalOptions": {
"skipFiles": [
"<node_internals>/**"
]
},
啟動配置
啟動配置是在 VS Code 中設定除錯的傳統方式,它為您運行復雜應用程式提供了最多的配置選項。
在本節中,我們將更詳細地探討針對更高階除錯場景的配置和功能。您將找到有關使用源對映進行除錯、跳過不感興趣的程式碼、進行遠端除錯等方面的說明。
如果您想觀看入門影片,請參閱VS Code 除錯入門。
注意:如果您剛開始使用 VS Code,可以在除錯主題中瞭解通用的除錯功能和建立
launch.json
配置檔案。
啟動配置屬性
除錯配置儲存在您工作區 .vscode
資料夾中的 launch.json
檔案中。有關除錯配置檔案建立和使用的介紹,請參閱通用除錯文章。
以下是 Node.js 偵錯程式特有的常見 launch.json
屬性參考。您可以在 vscode-js-debug 選項文件中檢視完整的選項集。
型別為 launch
和 attach
的啟動配置支援以下屬性:
outFiles
- 用於定位生成的 JavaScript 檔案的全域性模式陣列。請參閱源對映部分。resolveSourceMapLocations
- 應解析源對映位置的全域性模式陣列。請參閱源對映部分。timeout
- 重新啟動會話時,在此毫秒數後放棄。請參閱附加到 Node.js 部分。stopOnEntry
- 程式啟動時立即中斷。localRoot
- VS Code 的根目錄。請參閱下面的遠端除錯部分。remoteRoot
- Node 的根目錄。請參閱下面的遠端除錯部分。smartStep
- 嘗試自動跳過不對映到原始檔的程式碼。請參閱智慧單步執行部分。skipFiles
- 自動跳過這些全域性模式覆蓋的檔案。請參閱跳過不感興趣的程式碼部分。trace
- 啟用診斷輸出。
這些屬性僅適用於請求型別為 launch
的啟動配置:
program
- 要除錯的 Node.js 程式的絕對路徑。args
- 傳遞給要除錯的程式的引數。此屬性為陣列型別,期望將單個引數作為陣列元素。cwd
- 在此目錄中啟動要除錯的程式。runtimeExecutable
- 要使用的執行時可執行檔案的絕對路徑。預設為node
。請參閱對“npm”和其他工具的啟動配置支援部分。runtimeArgs
- 傳遞給執行時可執行檔案的可選引數。runtimeVersion
- 如果使用“nvm”(或“nvm-windows”)或“nvs”管理 Node.js 版本,則此屬性可用於選擇特定版本的 Node.js。請參閱下面的多版本支援部分。env
- 可選環境變數。此屬性期望環境變數為字串型別的鍵/值對列表。envFile
- 包含環境變數定義的檔案可選路徑。請參閱下面的從外部檔案載入環境變數部分。console
- 啟動程式的控制檯(internalConsole
、integratedTerminal
、externalTerminal
)。請參閱下面的Node 控制檯部分。outputCapture
- 如果設定為std
,程序 stdout/stderr 的輸出將顯示在除錯控制檯中,而不是透過除錯埠偵聽輸出。這對於直接寫入 stdout/stderr 流而不是使用console.*
API 的程式或日誌庫很有用。
此屬性僅適用於請求型別為 attach
的啟動配置:
restart
- 終止時重新啟動連線。請參閱自動重新啟動除錯會話部分。port
- 要使用的除錯埠。請參閱附加到 Node.js 和遠端除錯部分。address
- 除錯埠的 TCP/IP 地址。請參閱附加到 Node.js 和遠端除錯部分。processId
- 偵錯程式在傳送 USR1 訊號後嘗試附加到此程序。透過此設定,偵錯程式可以附加到未在除錯模式下啟動的已執行程序。使用processId
屬性時,除錯埠會根據 Node.js 版本(和使用的協議)自動確定,無法顯式配置。因此,不要指定port
屬性。continueOnAttach
- 如果我們附加到程序時它已暫停,是否繼續程序。如果您使用--inspect-brk
啟動程式,此選項很有用。
常見場景的啟動配置
您可以在 launch.json
檔案中觸發 IntelliSense (⌃Space (Windows, Linux Ctrl+Space)) 以檢視常用 Node.js 除錯場景的啟動配置程式碼片段。
您還可以透過 launch.json
編輯器視窗右下角的新增配置...按鈕調出程式碼片段。
以下程式碼片段可用:
- 啟動程式:以除錯模式啟動 Node.js 程式。
- 透過 npm 啟動:透過 npm“除錯”指令碼啟動 Node.js 程式。如果您的 package.json 中定義了 npm 除錯指令碼,您可以從啟動配置中使用它。npm 指令碼中使用的除錯埠必須與程式碼片段中指定的埠一致。
- 附加:附加到本地執行的 Node.js 程式的除錯埠。請確保要除錯的 Node.js 程式已在除錯模式下啟動,並且使用的除錯埠與程式碼片段中指定的埠相同。
- 附加到遠端程式:附加到在
address
屬性指定的主機上執行的 Node.js 程式的除錯埠。請確保要除錯的 Node.js 程式已在除錯模式下啟動,並且使用的除錯埠與程式碼片段中指定的埠相同。為了幫助 VS Code 在您的工作區和遠端主機的檔案系統之間對映原始檔,請務必為localRoot
和remoteRoot
屬性指定正確的路徑。 - 按程序 ID 附加:開啟程序選擇器以選擇要除錯的 node 或 gulp 程序。使用此啟動配置,您甚至可以附加到未在除錯模式下啟動的 node 或 gulp 程序。
- Nodemon 設定:使用 nodemon 在 JavaScript 原始檔更改時自動重新啟動除錯會話。請確保您已全域性安裝 nodemon。請注意,終止除錯會話只會終止要除錯的程式,而不會終止 nodemon 本身。要終止 nodemon,請在整合終端中按 Ctrl+C。
- Mocha 測試:除錯專案
test
資料夾中的 mocha 測試。請確保您的專案已在node_modules
資料夾中安裝了 'mocha'。 - Yeoman 生成器:除錯 yeoman 生成器。程式碼片段要求您指定生成器的名稱。請確保您的專案已在其
node_modules
資料夾中安裝了 'yo',並且透過在專案資料夾中執行npm link
已為除錯安裝了生成的專案。 - Gulp 任務:除錯 gulp 任務。請確保您的專案已在其
node_modules
資料夾中安裝了 'gulp'。 - Electron 主程序:除錯 Electron 應用程式的主 Node.js 程序。程式碼片段假定 Electron 可執行檔案已安裝在工作區的
node_modules/.bin
目錄中。
Node 控制檯
預設情況下,Node.js 除錯會話在 VS Code 內部除錯控制檯中啟動目標。由於除錯控制檯不支援需要從控制檯讀取輸入的程式,因此您可以透過將啟動配置中的 console
屬性分別設定為 externalTerminal
或 integratedTerminal
來啟用外部終端或使用 VS Code 整合終端。預設值為 internalConsole
。
在外部終端中,您可以透過 terminal.external.windowsExec
、terminal.external.osxExec
和 terminal.external.linuxExec
設定配置要使用的終端程式。
對“npm”和其他工具的啟動配置支援
您可以直接從啟動配置中使用“npm”指令碼或其他任務執行器工具,而不是直接用 node 啟動 Node.js 程式。
- 您可以將 PATH 上可用的任何程式(例如“npm”、“mocha”、“gulp”等)用於
runtimeExecutable
屬性,並且可以透過runtimeArgs
傳遞引數。 - 如果您的 npm 指令碼或其他工具隱式指定了要啟動的程式,則無需設定
program
屬性。
讓我們看一個“npm”示例。如果您的 package.json
有一個“debug”指令碼,例如:
"scripts": {
"debug": "node myProgram.js"
},
相應的啟動配置如下所示:
{
"name": "Launch via npm",
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}",
"runtimeExecutable": "npm",
"runtimeArgs": ["run-script", "debug"]
}
多版本支援
如果您使用“nvm”(或“nvm-windows”)來管理您的 Node.js 版本,則可以在啟動配置中指定 runtimeVersion
屬性來選擇特定版本的 Node.js:
{
"type": "node",
"request": "launch",
"name": "Launch test",
"runtimeVersion": "14",
"program": "${workspaceFolder}/test.js"
}
如果您使用“nvs”來管理您的 Node.js 版本,則可以使用 runtimeVersion
屬性選擇特定版本、架構和風格的 Node.js,例如:
{
"type": "node",
"request": "launch",
"name": "Launch test",
"runtimeVersion": "chackracore/8.9.4/x64",
"program": "${workspaceFolder}/test.js"
}
請確保已安裝要與 runtimeVersion
屬性一起使用的 Node.js 版本,因為該功能不會自動下載和安裝版本。例如,如果您打算將 "runtimeVersion": "7.10.1"
新增到您的啟動配置中,則必須從整合終端執行類似 nvm install 7.10.1
或 nvs add 7.10.1
的命令。
如果您省略次要版本和補丁版本,例如 "runtimeVersion": "14"
,則將使用您系統上安裝的最新 14.x.y
版本。
從外部檔案載入環境變數
VS Code Node 偵錯程式支援從檔案載入環境變數並將其傳遞給 Node.js 執行時。要使用此功能,請在啟動配置中新增 envFile
屬性並指定包含環境變數的檔案的絕對路徑:
//...
"envFile": "${workspaceFolder}/.env",
"env": { "USER": "john doe" }
//...
env
字典中指定的任何環境變數都將覆蓋從檔案載入的變數。
這是一個 .env
檔案的示例:
USER=doe
PASSWORD=abc123
# a comment
# an empty value:
empty=
# new lines expanded in quoted strings:
lines="foo\nbar"
附加到 Node.js
如果要將 VS Code 偵錯程式附加到外部 Node.js 程式,請按如下方式啟動 Node.js:
node --inspect program.js
或者,如果程式不應開始執行,但必須等待偵錯程式附加:
node --inspect-brk program.js
將偵錯程式附加到程式的選項:
- 開啟一個“程序選擇器”,列出所有潛在的候選程序並讓您選擇一個,或者
- 建立一個“附加”配置,顯式指定所有配置選項,然後按 F5。
讓我們詳細介紹這些選項:
附加到 Node 程序操作
命令面板(⇧⌘P (Windows, Linux Ctrl+Shift+P))中的附加到 Node 程序命令會開啟一個快速選擇選單,其中列出了 Node.js 偵錯程式可用的所有潛在程序:
選擇器中列出的各個程序顯示除錯埠和程序 ID。一旦您在該列表中選擇您的 Node.js 程序,Node.js 偵錯程式將嘗試附加到它。
除了 Node.js 程序之外,選擇器還會顯示其他以各種形式的 --inspect
引數啟動的程式。這使得可以附加到 Electron 或 VS Code 的輔助程序。
設定“附加”配置
此選項需要更多工作,但與前兩個選項相比,它允許您顯式配置各種除錯配置選項。
最簡單的“附加”配置如下所示:
{
"name": "Attach to Process",
"type": "node",
"request": "attach",
"port": 9229
}
埠 9229
是 --inspect
和 --inspect-brk
選項的預設除錯埠。要使用不同的埠(例如 12345
),請按如下方式將其新增到選項中:--inspect=12345
和 --inspect-brk=12345
,並更改啟動配置中的 port
屬性以匹配。
要附加到未在除錯模式下啟動的 Node.js 程序,您可以透過將 Node.js 程序的程序 ID 指定為字串來完成此操作:
{
"name": "Attach to Process",
"type": "node",
"request": "attach",
"processId": "53426"
}
為了避免在啟動配置中重複輸入新的程序 ID,Node 除錯支援一個命令變數 PickProcess
,它將開啟程序選擇器(如上)。
使用 PickProcess
變數,啟動配置如下所示:
{
"name": "Attach to Process",
"type": "node",
"request": "attach",
"processId": "${command:PickProcess}"
}
停止除錯
使用除錯:停止操作(可在除錯工具欄或透過命令面板獲得)可停止除錯會話。
如果除錯會話以“附加”模式啟動(並且除錯工具欄中的紅色終止按鈕顯示疊加的“插頭”),則按停止會斷開 Node.js 偵錯程式與除錯目標的連線,然後除錯目標將繼續執行。
如果除錯會話處於“啟動”模式,則按停止將執行以下操作:
-
首次按下停止時,偵錯程式會透過傳送
SIGINT
訊號請求除錯目標優雅關閉。除錯目標可以自由攔截此訊號並根據需要清理任何內容,然後關閉。如果該關閉程式碼中沒有斷點(或問題),則除錯目標和除錯會話將終止。 -
但是,如果偵錯程式在關閉程式碼中命中斷點,或者如果除錯目標本身無法正常終止,則除錯會話將不會結束。在這種情況下,再次按下停止將強制終止除錯目標及其子程序(
SIGKILL
)。
如果您發現除錯會話在按下紅色停止按鈕時沒有結束,請再次按下該按鈕以強制關閉除錯目標。
在 Windows 上,按下停止會強制終止除錯目標及其子程序。
源對映
VS Code 的 JavaScript 偵錯程式支援源對映,有助於除錯轉譯語言,例如 TypeScript 或縮小/混淆的 JavaScript。藉助源對映,可以單步執行或在原始源中設定斷點。如果原始源不存在源對映,或者源對映損壞且無法成功在源和生成的 JavaScript 之間對映,則斷點會顯示為未驗證(灰色空心圓圈)。
預設為 true
的 sourceMaps
屬性控制源對映功能。偵錯程式始終嘗試使用源對映(如果能找到),因此,您甚至可以使用 program
屬性指定原始檔(例如 app.ts)。如果出於某種原因需要停用源對映,可以將 sourceMaps
屬性設定為 false
。
工具配置
由於源對映並非總是自動建立,因此您應確保配置轉譯器以建立它們。例如:
TypeScript
對於 TypeScript,您可以向 tsc
傳遞 --sourceMap
,或在 tsconfig.json 檔案中新增 "sourceMap": true
來啟用源對映。
tsc --sourceMap --outDir bin app.ts
Babel
對於 Babel,您需要將 sourceMaps 選項設定為 true
,或在編譯程式碼時傳遞 --source-maps
選項。
npx babel script.js --out-file script-compiled.js --source-maps
Webpack
Webpack 有眾多源對映選項。我們建議在 webpack.config.js
中將屬性 devtool: "source-map"
設定為最高保真度的結果,儘管您可以嘗試其他可能導致構建速度減慢的設定。
此外,如果您在 webpack 中有額外的編譯步驟,例如使用 TypeScript 載入器,您還需要確保這些步驟設定為生成源對映。否則,webpack 生成的源對映將映射回載入器編譯的程式碼,而不是真實源。
源對映發現
預設情況下,VS Code 將搜尋您的整個工作區(排除 node_modules
)以查詢源對映。在大型工作區中,此搜尋可能會很慢。您可以透過在 launch.json
中設定 outFiles
屬性來配置 VS Code 搜尋源對映的位置。例如,此配置將僅發現 bin
資料夾中 .js
檔案的源對映:
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch TypeScript",
"type": "node",
"request": "launch",
"program": "app.ts",
"outFiles": ["${workspaceFolder}/bin/**/*.js"]
}
]
}
請注意,outFiles
應該與您的 JavaScript 檔案匹配,而不是源對映檔案(它們可能以 .map
結尾而不是 .js
)。
源對映解析
預設情況下,只解析 outFiles
中的源對映。此行為用於防止依賴項干擾您設定的斷點。例如,如果您有一個檔案 src/index.ts
,而一個依賴項有一個引用 webpack:///./src/index.ts
的源對映,這會錯誤地解析到您的原始檔,並可能導致意外結果。
您可以透過設定 resolveSourceMapLocations
選項來配置此行為。如果設定為 null
,則將解析所有源對映。例如,此配置將額外允許解析 node_modules/some-dependency
中的源對映:
"resolveSourceMapLocations": [
"out/**/*.js",
"node_modules/some-dependency/**/*.js",
]
智慧單步執行
在啟動配置中將 smartStep
屬性設定為 true
時,VS Code 會在偵錯程式中單步執行程式碼時自動跳過“不感興趣的程式碼”。“不感興趣的程式碼”是轉譯過程生成的程式碼,但不受源對映覆蓋,因此它不映射回原始源。當在偵錯程式中單步執行原始碼時,此程式碼會妨礙您,因為它會使偵錯程式在原始原始碼和您不感興趣的生成程式碼之間切換。smartStep
會自動單步執行不受源對映覆蓋的程式碼,直到再次到達受源對映覆蓋的位置。
智慧單步執行對於 TypeScript 中 async/await 的下層編譯尤其有用,其中編譯器注入了不受源對映覆蓋的輔助程式碼。
smartStep
功能僅適用於從原始碼生成的 JavaScript 程式碼,因此具有源對映。對於沒有源的 JavaScript,智慧單步執行選項無效。
JavaScript 源對映技巧
使用源對映除錯時常見的一個問題是,您設定了斷點,它會變成灰色。如果您將游標懸停在其上方,您會看到訊息:“Breakpoint ignored because generated code not found (source map problem?)”(斷點被忽略,因為未找到生成的程式碼(源對映問題?))。現在怎麼辦?導致這種情況的原因有很多。首先,簡要解釋一下 Node 除錯介面卡如何處理源對映。
當您在 app.ts
中設定斷點時,除錯介面卡必須找出 app.js
的路徑,即您的 TypeScript 檔案的轉譯版本,這是實際在 Node 中執行的檔案。但是,從 .ts
檔案開始,並沒有直接的方法來找出這一點。相反,除錯介面卡使用 launch.json
中的 outFiles
屬性來查詢所有轉譯後的 .js
檔案,並解析它們以獲取源對映,其中包含其關聯的 .ts
檔案的位置。
當您使用啟用源對映的 TypeScript 構建 app.ts
檔案時,它會生成一個 app.js.map
檔案,或者在 app.js
檔案底部以 base64 編碼字串的形式內聯源對映。為了找到與此對映關聯的 .ts
檔案,除錯介面卡會檢視源對映中的兩個屬性:sources
和 sourceRoot
。sourceRoot
是可選的 - 如果存在,它會新增到 sources
中的每個路徑前面,sources
是一個路徑陣列。結果是一個 .ts
檔案的絕對或相對路徑陣列。相對路徑相對於源對映解析。
最後,除錯介面卡在此生成的 .ts
檔案列表中搜索 app.ts
的完整路徑。如果匹配,則它已找到用於將 app.ts
對映到 app.js
的源對映檔案。如果不匹配,則無法繫結斷點,並且它將變為灰色。
當您的斷點變為灰色時,您可以嘗試以下幾點:
- 在除錯時,執行除錯:診斷斷點問題命令。此命令將調出一個工具,可以提供提示以幫助您解決命令面板(⇧⌘P (Windows, Linux Ctrl+Shift+P))中的任何問題。
- 您是否在構建時啟用了源對映?請確保您的
.js
檔案中有.js.map
檔案或內聯源對映。 - 您的源對映中的
sourceRoot
和sources
屬性是否正確?它們可以組合以獲取.ts
檔案的正確路徑嗎? - 您是否以不正確的區分大小寫方式在 VS Code 中打開了資料夾?可以從命令列以
code FOO
的形式開啟foo/
資料夾,在這種情況下,源對映可能無法正確解析。 - 嘗試在 Stack Overflow 上搜索有關您特定設定的幫助,或在 GitHub 上提交問題。
- 嘗試新增
debugger
語句。如果它在該位置中斷到.ts
檔案中,但該位置的斷點未繫結,則這是在 GitHub 問題中包含的有用資訊。
覆蓋源對映路徑
偵錯程式使用 sourceMapPathOverrides
實現自定義源對映到磁碟路徑對映。大多數工具都有良好的預設設定,但在高階情況下,您可能需要自定義它。預設的路徑覆蓋是一個物件對映,如下所示:
{
'webpack:///./~/*': "${workspaceFolder}/node_modules/*",
'webpack:////*': '/*',
'webpack://@?:*/?:*/*': "${workspaceFolder}/*",
// and some more patterns...
}
這會將源對映中的路徑或 URL 從左側對映到右側。模式 ?:*
是非貪婪、非捕獲匹配,而 *
是貪婪捕獲匹配。然後,偵錯程式將右側模式中相應的 *
替換為從源對映路徑捕獲的片段。例如,上面示例中的最後一個模式會將 webpack://@my/package/foo/bar
對映到 ${workspaceFolder}/foo/bar
。
請注意,對於瀏覽器除錯,預設的 sourceMapPathOverrides
中使用 webRoot
代替 workspaceFolder
。
遠端除錯
注意:VS Code 現在具有通用的遠端開發功能。使用遠端開發擴充套件,遠端場景和容器中的 Node.js 開發與本地設定中的 Node.js 開發沒有區別。這是遠端除錯 Node.js 程式的推薦方式。檢視入門部分和遠端教程以瞭解更多資訊。
如果您無法使用任何遠端開發擴充套件來除錯您的 Node.js 程式,下面是如何從您的本地 VS Code 例項除錯遠端 Node.js 程式的指南。
Node.js 偵錯程式支援遠端除錯,您可以附加到在不同機器或容器中執行的程序。透過 address
屬性指定遠端主機。例如:
{
"type": "node",
"request": "attach",
"name": "Attach to remote",
"address": "192.168.148.2", // <- remote address here
"port": 9229
}
預設情況下,VS Code 會將除錯過的源從遠端 Node.js 資料夾流式傳輸到本地 VS Code,並在只讀編輯器中顯示。您可以單步執行此程式碼,但無法修改它。如果您希望 VS Code 改為從工作區開啟可編輯的源,您可以設定遠端和本地位置之間的對映。localRoot
和 remoteRoot
屬性可用於對映本地 VS Code 專案和(遠端)Node.js 資料夾之間的路徑。這甚至可以在同一系統上或跨不同作業系統本地工作。每當需要將程式碼路徑從遠端 Node.js 資料夾轉換為本地 VS Code 路徑時,remoteRoot
路徑將從路徑中刪除並替換為 localRoot
。對於反向轉換,localRoot
路徑將替換為 remoteRoot
。
{
"type": "node",
"request": "attach",
"name": "Attach to remote",
"address": "TCP/IP address of process to be debugged",
"port": 9229,
"localRoot": "${workspaceFolder}",
"remoteRoot": "C:\\Users\\username\\project\\server"
}
訪問已載入指令碼
如果您需要在不屬於您的工作區且因此無法透過普通 VS Code 檔案瀏覽輕鬆找到和開啟的指令碼中設定斷點,您可以透過執行和除錯檢視中的已載入指令碼檢視訪問已載入指令碼:
當啟用型別篩選開啟時,已載入指令碼檢視允許您透過鍵入其名稱快速選擇指令碼或篩選列表。
指令碼被載入到只讀編輯器中,您可以在其中設定斷點。這些斷點會在除錯會話之間記住,但您只有在除錯會話執行時才能訪問指令碼內容。
原始檔編輯時自動重新啟動除錯會話
啟動配置的 restart
屬性控制 Node.js 偵錯程式在除錯會話結束後是否自動重新啟動。如果您使用 nodemon 在檔案更改時重新啟動 Node.js,此功能非常有用。將啟動配置屬性 restart
設定為 true
會使 Node 偵錯程式在 Node.js 終止後自動嘗試重新附加到 Node.js。
如果您已透過命令列中的 nodemon 啟動您的程式 server.js
,如下所示:
nodemon --inspect server.js
您可以使用以下啟動配置將 VS Code 偵錯程式附加到它:
{
"name": "Attach to node",
"type": "node",
"request": "attach",
"restart": true,
"port": 9229
}
或者,您可以使用啟動配置直接透過 nodemon 啟動您的程式 server.js
並附加 VS Code 偵錯程式:
{
"name": "Launch server.js via nodemon",
"type": "node",
"request": "launch",
"runtimeExecutable": "nodemon",
"program": "${workspaceFolder}/server.js",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
}
提示:按下停止按鈕會停止除錯會話並斷開與 Node.js 的連線,但 nodemon(和 Node.js)將繼續執行。要停止 nodemon,您必須從命令列終止它(如果您使用
integratedTerminal
,如上所示,這很容易做到)。
提示:如果存在語法錯誤,nodemon 將無法成功啟動 Node.js,直到錯誤得到修復。在這種情況下,VS Code 將繼續嘗試附加到 Node.js,但最終會放棄(10 秒後)。為避免這種情況,您可以透過新增具有更大值(以毫秒為單位)的
timeout
屬性來增加超時。
重新啟動幀
Node 偵錯程式支援在堆疊幀處重新啟動執行。這在您發現原始碼中的問題並希望使用修改後的輸入值重新執行一小部分程式碼時非常有用。停止然後重新啟動完整的除錯會話可能非常耗時。重新啟動幀操作允許您在使用設定值操作更改變數後重新進入當前函式:
重新啟動幀不會回滾函式外部的狀態更改,因此它可能並不總是按預期工作。
Breakpoints
條件斷點
條件斷點是指僅當表示式返回真值時才暫停的斷點。您可以透過右鍵單擊行號旁邊的邊槽並選擇“條件斷點”來建立它。
日誌點
有時您只想在程式碼到達某個位置時記錄訊息或值,而不是暫停。您可以使用日誌點來實現此目的。日誌點不會暫停,而是在命中時將訊息記錄到除錯控制檯。在 JavaScript 偵錯程式中,您可以使用花括號將表示式插入到訊息中,例如 當前值為: {myVariable.property}
。
您可以透過右鍵單擊行號旁邊的邊槽並選擇“日誌點”來建立它。例如,這可能會記錄類似 位置是 /usr/local
的內容。
命中次數斷點
“命中計數條件”控制斷點需要命中多少次才能“中斷”執行。您可以透過右鍵單擊行號旁邊的邊槽,選擇“條件斷點”,然後切換到“命中計數”來放置命中計數斷點。
Node.js 偵錯程式支援的命中計數語法可以是整數,也可以是 <
、<=
、==
、>
、>=
、%
運算子後跟一個整數。
一些示例
>10
在命中 10 次後總是中斷<3
只在第一次和第二次命中時中斷10
與>=10
相同%2
每隔一次命中中斷
觸發斷點
觸發斷點是一種在另一個斷點命中後自動啟用的斷點。當代碼中出現僅在特定先決條件發生後才出現的故障情況時,它們非常有用。
可以透過右鍵單擊字形邊距,選擇 新增觸發斷點,然後選擇哪個其他斷點啟用此斷點來設定觸發斷點。
斷點驗證
出於效能原因,Node.js 在第一次訪問時懶惰地解析 JavaScript 檔案中的函式。因此,斷點在 Node.js 尚未看到(解析)的原始碼區域中不起作用。
由於此行為不利於除錯,VS Code 會自動將 --nolazy
選項傳遞給 Node.js。這可以防止延遲解析,並確保斷點可以在執行程式碼之前進行驗證(因此它們不再“跳躍”)。
由於 --nolazy
選項可能會顯著增加除錯目標的啟動時間,您可以透過將 --lazy
作為 runtimeArgs
屬性傳遞來輕鬆退出。
這樣做時,您會發現您的某些斷點沒有“粘附”到請求的行,而是“跳躍”到已解析程式碼中的下一個可能行。為了避免混淆,VS Code 始終在 Node.js 認為斷點所在的位置顯示斷點。在斷點部分中,這些斷點顯示一個請求行號和實際行號之間的箭頭:
此斷點驗證發生在會話啟動並將斷點註冊到 Node.js 時,或會話已執行並設定新斷點時。在這種情況下,斷點可能會“跳躍”到不同的位置。在 Node.js 解析所有程式碼(例如,透過執行它)後,可以使用斷點部分標題中的重新應用按鈕輕鬆地將斷點重新應用到請求的位置。這應該會使斷點“跳回”到請求的位置。
跳過不感興趣的程式碼
VS Code Node.js 除錯具有一項功能,可避免您不想單步執行的原始碼(也稱為“僅我的程式碼”)。此功能可以透過啟動配置中的 skipFiles
屬性啟用。skipFiles
是用於跳過指令碼路徑的全域性模式陣列。
例如,使用
"skipFiles": [
"${workspaceFolder}/node_modules/**/*.js",
"${workspaceFolder}/lib/**/*.js"
]
專案中 node_modules
和 lib
資料夾中的所有程式碼都將被跳過。skipFiles
也適用於呼叫 console.log
和類似方法時顯示的位置:堆疊中第一個未跳過的位置將顯示在除錯控制檯的輸出旁邊。
Node.js 的內建核心模組可以透過全域性模式中的“魔術名稱”
來引用。以下示例跳過所有內部模組:
"skipFiles": [
"<node_internals>/**/*.js"
]
確切的“跳過”規則如下:
- 如果您單步進入一個跳過的檔案,您將不會在那裡停止 - 您將停止在不在跳過的檔案中的下一個執行行。
- 如果您已設定在丟擲異常時中斷的選項,那麼您將不會在從跳過檔案丟擲的異常處中斷,除非它們冒泡到未跳過的檔案中。
- 如果您在跳過檔案中設定斷點,您將在此斷點處停止,並且您將能夠單步執行它,直到您單步跳出它,此時將恢復正常的跳過行為。
- 來自跳過檔案內部的控制檯訊息的位置將顯示為呼叫堆疊中的第一個未跳過位置。
跳過的原始碼在呼叫堆疊檢視中以“模糊”樣式顯示:
將滑鼠懸停在模糊的條目上會解釋堆疊幀模糊的原因。
呼叫堆疊上的上下文選單項“切換跳過此檔案”使您能夠輕鬆地在執行時跳過檔案,而無需將其新增到您的啟動配置中。此選項僅在當前除錯會話中持久。您也可以使用它來停止跳過您的啟動配置中 skipFiles
選項跳過的檔案。
注意:
legacy
協議偵錯程式支援負全域性模式,但它們必須跟隨正模式:正模式新增到跳過檔案集,而負模式從該集合中減去。
在以下(僅限 legacy
協議)示例中,除了“math”模組之外的所有模組都將被跳過:
"skipFiles": [
"${workspaceFolder}/node_modules/**/*.js",
"!${workspaceFolder}/node_modules/math/**/*.js"
]
注意:
legacy
協議偵錯程式必須模擬skipFiles
功能,因為 V8 偵錯程式協議不支援它。這可能會導致單步執行效能緩慢。
除錯 WebAssembly
JavaScript 偵錯程式可以除錯編譯成 WebAssembly 的程式碼,如果它包含 DWARF 除錯資訊。許多工具鏈都支援發出此資訊:
- 使用 Emscripten 的 C/C++:使用
-g
標誌編譯以發出除錯資訊。 - Zig:DWARF 資訊在“除錯”構建模式下自動發出。
- Rust:Rust 會發出 DWARF 除錯資訊。但是,wasm-pack 尚未在構建過程中保留它。因此,wasm-bindgen/wasm-pack 庫的使用者應手動使用兩個命令構建,而不是執行
wasm-pack build
:cargo install wasm-bindgen-cli
一次安裝必要的命令列工具。cargo build --target wasm32-unknown-unknown
構建您的庫。wasm-bindgen --keep-debug --out-dir pkg ./target/wasm32-unknown-unknown/debug/<library-name>.wasm <extra-arguments>
生成 WebAssembly 繫結,將<library-name>
替換為您 Cargo.toml 中的名稱並根據需要配置<extra-arguments>
。
構建程式碼後,您需要安裝 WebAssembly DWARF Debugging 擴充套件。這是作為單獨的擴充套件釋出的,以保持 VS Code 核心“精簡”。安裝後,重新啟動任何活動的除錯會話,然後本機程式碼應該在偵錯程式中對映!您應該會在已載入源檢視中看到您的原始碼,並且斷點應該可以工作。
在下圖中,偵錯程式在 C++ 原始碼中的一個斷點處停止,該原始碼建立了一個 Mandelbrot 分形。呼叫堆疊可見,其中包含來自 JavaScript 程式碼、WebAssembly 和對映的 C++ 程式碼的幀。您還可以看到 C++ 程式碼中的變數,以及對與 int32 height
變數關聯的記憶體的編輯。
雖然與普通 JavaScript 除錯幾乎相同,但除錯 WebAssembly 略有不同:
- 變數檢視中的變數無法直接編輯。但是,您可以選擇變數旁邊的檢視二進位制資料操作來編輯其關聯的記憶體。
- 除錯控制檯和監視檢視中的基本表示式求值由 lldb-eval 提供。這與普通 JavaScript 表示式不同。
- 未對映到原始碼的位置將以反彙編的 WebAssembly 文字格式顯示。對於 WebAssembly,命令停用源對映單步執行將導致偵錯程式僅在反彙編程式碼中單步執行。
VS Code 的 WebAssembly 除錯基於 Chromium 作者的 C/C++ Debugging Extension 構建。
支援的類 Node 執行時
當前的 VS Code JavaScript 偵錯程式支援 Node 8.x 及以上版本、最新 Chrome 版本和最新 Edge 版本(透過 msedge
啟動型別)。
後續步驟
如果您還沒有閱讀 Node.js 部分,請檢視:
- Node.js - 使用示例應用程式的端到端 Node 場景
要觀看 VS Code 除錯基礎教程,請檢視此影片:
要了解 VS Code 的任務執行支援,請訪問:
- 任務 - 使用 Gulp、Grunt 和 Jake 執行任務。顯示錯誤和警告
要編寫您自己的偵錯程式擴充套件,請訪問:
- 偵錯程式擴充套件 - 從模擬示例開始建立 VS Code 除錯擴充套件的步驟
常見問題
如果我使用符號連結,我可以除錯嗎?
可以,如果您已為專案中的資料夾建立了符號連結,例如使用 npm link
,您可以透過告訴 Node.js 執行時保留符號連結路徑來除錯符號連結源。在您的啟動配置 runtimeArgs
屬性中使用 node.exe --preserve-symlinks
開關。runtimeArgs
是一個字串陣列,傳遞給除錯會話執行時可執行檔案,預設為 node.exe。
{
"runtimeArgs": ["--preserve-symlinks"]
}
如果您的主指令碼在符號連結路徑中,那麼您還需要新增 "--preserve-symlinks-main"
選項。此選項僅在 Node 10+ 中可用。
如何除錯 ECMAScript 模組?
如果您使用 esm 或將 --experimental-modules
傳遞給 Node.js 以使用 ECMAScript 模組,您可以透過 launch.json
的 runtimeArgs
屬性傳遞這些選項:
"runtimeArgs": ["--experimental-modules"]
- 在 Node v8.5.0+ 中使用實驗性 ECMAScript 模組支援"runtimeArgs": ["-r", "esm"]
- 使用 esm ES 模組載入器(["-r esm"]
不帶逗號將不起作用)
如何設定 NODE_OPTIONS?
偵錯程式使用特殊的 NODE_OPTIONS
環境變數來設定與您的應用程式的除錯,覆蓋它將阻止除錯正常工作。您應該追加而不是覆蓋它。例如,.bashrc
檔案可能包含以下內容:
export NODE_OPTIONS="$NODE_OPTIONS --some-other-option=here"