現已釋出!閱讀關於 11 月新增功能和修復的內容。

VS Code 中的 Node.js 除錯

Visual Studio Code 編輯器內建了對 Node.js 執行時的除錯支援,並且可以除錯 JavaScript、TypeScript 以及許多其他可以轉譯為 JavaScript 的語言。使用 VS Code 設定 Node.js 除錯專案非常簡單,它提供了合適的啟動配置預設值和程式碼片段。

在 VS Code 中除錯 Node.js 程式有幾種方法:

自動附加

如果啟用了 **自動附加** 功能,Node 偵錯程式會自動附加到從 VS Code 整合終端啟動的某些 Node.js 程序。要啟用此功能,請透過命令面板(⇧⌘P (Windows、Linux Ctrl+Shift+P))使用 **切換自動附加** 命令,或者如果它已啟用,則使用狀態列中的 **自動附加** 狀態列項。

自動附加有三種模式,您可以在出現的快速選擇選單中以及透過 **debug.javascript.autoAttachFilter** 設定進行選擇。

  • smart - 如果您在 `node_modules` 資料夾外部執行指令碼,或者使用常見的“執行指令碼”(如 mocha 或 ts-node),則該程序將被除錯。您可以使用 **自動附加智慧模式** 設定 (`debug.javascript.autoAttachSmartPattern`) 來配置“執行指令碼”允許列表。
  • always - 整合終端中啟動的所有 Node.js 程序都將被除錯。
  • onlyWithFlag - 僅除錯使用 `--inspect` 或 `--inspect-brk` 標誌啟動的程序。

啟用 **自動附加** 後,您需要透過單擊終端右上角的 ⚠ 圖示來重新啟動終端,或者直接建立一個新的終端。然後,偵錯程式應該會在一秒鐘內附加到您的程式。

Auto Attach

當自動附加開啟時,`Auto Attach` 項會出現在 VS Code 視窗底部的狀態列。單擊它可以更改自動附加模式,或臨時將其關閉。臨時關閉自動附加對於執行一些一次性程式很有用,您不需要除錯,但也不想完全停用該功能。

附加配置

其他啟動配置屬性

您可以將 `launch.json` 中常見的 其他屬性 應用於自動附加,方法是在 **debug.javascript.terminalOptions** 設定中進行配置。例如,要將 Node 內部檔案新增到您的 skipFiles,您可以將以下內容新增到您的使用者或工作區設定中。

  "debug.javascript.terminalOptions": {
    "skipFiles": [
      "<node_internals>/**"
    ]
  },

自動附加智慧模式

在 `smart` 自動附加模式下,VS Code 會嘗試附加到您的程式碼,而不是附加到您不感興趣的構建工具。它透過將主指令碼與 glob 模式 列表進行匹配來實現。Glob 模式可以在 **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 程序。您可以透過在命令面板中執行 **Debug: Create JavaScript Debug Terminal** 命令 (`kbs(workbench.action.showCommands)`),或從終端選擇器下拉選單中選擇 **Create JavaScript Debug Terminal** 來建立除錯終端。

Create Debug Terminal

附加配置

其他啟動配置屬性

您可以將 `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 options 文件中檢視所有可用選項。

以下屬性支援型別為 `launch` 和 `attach` 的啟動配置:

  • outFiles - 用於查詢生成的 JavaScript 檔案的 glob 模式 陣列。請參閱 源對映 部分。
  • resolveSourceMapLocations - 用於解析源對映位置的 glob 模式 陣列。請參閱 源對映 部分。
  • timeout - 重啟會話時,等待此毫秒數後放棄。請參閱 附加到 Node.js 部分。
  • stopOnEntry - 程式啟動時立即中斷。
  • localRoot - VS Code 的根目錄。請參閱下面的 遠端除錯 部分。
  • remoteRoot - Node 的根目錄。請參閱下面的 遠端除錯 部分。
  • smartStep - 嘗試自動跳過不對映到原始檔的程式碼。請參閱 智慧步進 部分。
  • skipFiles - 自動跳過由這些 glob 模式 覆蓋的檔案。請參閱 跳過不相關的程式碼 部分。
  • 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 的輸出將顯示在 Debug Console 中,而不是透過除錯埠偵聽輸出。這對於直接寫入 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 configuration snippets for Node.js

您還可以透過 `launch.json` 編輯器視窗右下角的 **Add Configuration...** 按鈕來調出程式碼片段。

Add Configuration button

以下程式碼片段可用:

  • Launch Program:以除錯模式啟動 Node.js 程式。
  • Launch via npm:透過 npm 的 'debug' 指令碼啟動 Node.js 程式。如果您的 `package.json` 中已定義了 npm 除錯指令碼,則可以在啟動配置中使用它。npm 指令碼中使用的除錯埠必須與程式碼片段中指定的埠相對應。
  • Attach:附加到本地執行的 Node.js 程式的除錯埠。請確保要除錯的 Node.js 程式已在除錯模式下啟動,並且使用的除錯埠與程式碼片段中指定的埠相同。
  • Attach to Remote Program:附加到由 `address` 屬性指定的遠端主機上執行的 Node.js 程式的除錯埠。請確保要除錯的 Node.js 程式已在除錯模式下啟動,並且使用的除錯埠與程式碼片段中指定的埠相同。為了幫助 VS Code 在工作區和遠端主機的檔案系統之間對映原始檔,請務必為 `localRoot` 和 `remoteRoot` 屬性指定正確的路徑。
  • Attach by Process ID:開啟程序選擇器,選擇一個 node 或 gulp 程序進行除錯。使用此啟動配置,您甚至可以附加到未以除錯模式啟動的 node 或 gulp 程序。
  • Nodemon Setup:使用 nodemon 在 JavaScript 原始檔更改時自動重新啟動除錯會話。請確保您已全域性安裝 nodemon。請注意,終止除錯會話僅終止要除錯的程式,而不終止 nodemon 本身。要終止 nodemon,請在整合終端中按 Ctrl+C
  • Mocha Tests:除錯專案 `test` 資料夾中的 mocha 測試。請確保您的專案在其 `node_modules` 資料夾中已安裝 'mocha'。
  • Yeoman generator:除錯 yeoman 生成器。程式碼片段會要求您指定生成器的名稱。請確保您的專案在其 `node_modules` 資料夾中已安裝 'yo',並且您透過在專案資料夾中執行 `npm link` 來安裝您的生成專案以進行除錯。
  • Gulp task:除錯 gulp 任務。請確保您的專案在其 `node_modules` 資料夾中已安裝 'gulp'。
  • Electron Main:除錯 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

附加到程式的除錯選項

  • 開啟一個“程序選擇器”,該選擇器列出所有潛在的候選程序並允許您選擇一個,或者
  • 建立一個“attach”配置,明確指定所有配置選項,然後按 **F5**。

讓我們詳細瞭解這些選項:

Attach to Node Process 操作

從命令面板(⇧⌘P (Windows、Linux Ctrl+Shift+P))執行 **Attach to Node Process** 命令會開啟一個快速選擇選單,其中列出了 Node.js 偵錯程式可用的所有潛在程序。

Node.js Process picker

選擇器中列出的各個程序顯示了除錯埠和程序 ID。一旦您在列表中選擇了您的 Node.js 程序,Node.js 偵錯程式就會嘗試附加到它。

除了 Node.js 程序外,選擇器還顯示了使用各種形式的 `--inspect` 引數啟動的其他程式。這使得可以附加到 Electron 或 VS Code 的輔助程序。

設定“Attach”配置

此選項需要更多工作,但與前兩個選項相比,它允許您顯式配置各種除錯配置選項。

最簡單的“attach”配置如下所示:

{
  "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}"
}

停止除錯

使用 **Debug: Stop** 操作(在除錯工具欄或透過 **Command Palette** 中可用)可以停止除錯會話。

如果除錯會話是在“attach”模式下啟動的(並且除錯工具欄中的紅色終止按鈕顯示一個疊加的“插頭”),按 **Stop** 會斷開 Node.js 偵錯程式與被除錯程式的連線,然後被除錯程式會繼續執行。

如果除錯會話處於“launch”模式,按 **Stop** 會執行以下操作:

  1. 當第一次按 **Stop** 時,將透過傳送 `SIGINT` 訊號請求被除錯程式優雅關閉。被除錯程式可以自行攔截此訊號並進行必要的清理,然後關閉。如果其中沒有斷點(或問題),則被除錯程式和除錯會話將終止。

  2. 但是,如果偵錯程式在關閉程式碼中命中了一個斷點,或者被除錯程式沒有自行正確終止,那麼除錯會話將不會結束。在這種情況下,再次按 **Stop** 將強制終止被除錯程式及其子程序(`SIGKILL`)。

如果您發現按除錯工具欄中的紅色 **Stop** 按鈕後除錯會話沒有結束,請再次按該按鈕以強制關閉被除錯程式。

在 Windows 上,按 **Stop** 會強制終止被除錯程式及其子程序。

源對映

VS Code 的 JavaScript 偵錯程式支援源對映,這有助於除錯轉譯的語言,例如 TypeScript 或最小化/混淆的 JavaScript。透過源對映,可以單步執行或在原始源中設定斷點。如果原始源沒有源對映,或者源對映已損壞且無法成功對映源和生成的 JavaScript 之間的關係,則斷點將顯示為未驗證(灰色空心圓)。

`sourceMaps` 屬性(預設為 `true`)控制源對映功能。偵錯程式始終嘗試使用源對映(如果能找到的話),因此,您甚至可以使用 `program` 屬性指定一個原始檔(例如,app.ts)。如果您出於某種原因需要停用源對映,可以將 `sourceMaps` 屬性設定為 `false`。

工具配置

由於源對映並非總是自動建立,因此您應確保配置您的轉譯器以建立它們。例如:

TypeScript

對於 TypeScript,可以透過將 ` --sourceMap ` 傳遞給 ` tsc `,或者在 tsconfig.json 檔案中新增 ` "sourceMap": true ` 來啟用 sourcemaps。

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 載入器,您還需要確保這些步驟已設定為生成 sourcemaps。否則,Webpack 生成的 sourcemaps 將映射回載入器的編譯程式碼,而不是實際源。

源對映發現

預設情況下,VS Code 會搜尋整個工作區(排除 `node_modules`)以查詢 sourcemaps。在大型工作區中,此搜尋可能很慢。您可以透過在 `launch.json` 中設定 `outFiles` 屬性來配置 VS Code 搜尋源對映的位置。例如,此配置將僅發現 `bin` 資料夾中 `.js` 檔案的 sourcemaps:

{
  "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` 檔案,或者一個以 base64 編碼字串形式內嵌在 `app.js` 檔案底部註釋中的源對映。為了找到與此對映關聯的 `.ts` 檔案,除錯介面卡會檢視源對映中的兩個屬性:`sources` 和 `sourceRoot`。`sourceRoot` 是可選的 - 如果存在,它會新增到 `sources`(一個路徑陣列)中的每個路徑前面。結果是 `.ts` 檔案的絕對或相對路徑。相對路徑是相對於源對映解析的。

最後,除錯介面卡在此生成的 `.ts` 檔案列表中搜索 `app.ts` 的完整路徑。如果找到匹配項,它就找到了用於將 `app.ts` 對映到 `app.js` 的源對映檔案。如果沒有匹配項,則無法繫結斷點,它將變為灰色。

以下是一些嘗試解決斷點變灰問題的建議:

  • 除錯時,執行 **Debug: Diagnose Breakpoint Problems** 命令。該命令將開啟一個工具,可以提供提示以幫助您從命令面板(⇧⌘P (Windows、Linux Ctrl+Shift+P))中解決任何問題。
  • 您是否啟用了源對映進行構建?確保您的 `.js` 檔案中有 `.js.map` 檔案或內嵌的源對映。
  • 您的源對映中的 `sourceRoot` 和 `sources` 屬性是否正確?它們是否可以組合以獲得 `.ts` 檔案的正確路徑?
  • 您是否以不正確的案例打開了 VS Code 中的資料夾?有可能從命令列透過 `code FOO` 開啟資料夾 `foo/`,在這種情況下,源對映可能無法正確解析。
  • 嘗試在 Stack Overflow 上搜索關於您特定設定的幫助,或在 GitHub 上提交 issue。
  • 嘗試新增一個 `debugger` 語句。如果它在 `.ts` 檔案中中斷,但在該位置的斷點沒有繫結,那麼這些資訊對於提交 GitHub issue 很有用。

覆蓋源對映路徑

偵錯程式使用 `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 現在具有通用的 遠端開發功能。使用 Remote Development 擴充套件,在遠端場景和容器中進行 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 檔案瀏覽輕鬆找到和開啟的指令碼中設定斷點,您可以透過 **Run and Debug** 檢視中的 **LOADED SCRIPTS** 檢視來訪問已載入的指令碼。

Loaded Scripts Explorer

當 **Enable Filter on Type** 開啟時,**LOADED SCRIPTS** 檢視允許您透過輸入指令碼名稱快速選擇指令碼或過濾列表。

指令碼會被載入到一個只讀編輯器中,您可以在其中設定斷點。這些斷點會在除錯會話之間保留,但您只能在除錯會話執行時訪問指令碼內容。

原始檔編輯時自動重啟除錯會話

啟動配置的 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 偵錯程式支援在堆疊幀處重新啟動執行。在您發現原始碼中的問題並希望使用修改後的輸入值重新執行一小段程式碼的情況下,這可能很有用。停止然後重新啟動整個除錯會話可能非常耗時。重新啟動幀 操作允許您在透過 設定值 操作更改變數後重新進入當前函式。

Restart frame

重新啟動幀 不會回滾對函式外部狀態的修改,因此它可能不總是按預期工作。

Breakpoints

條件斷點

條件斷點是僅在表示式返回真值時才暫停的斷點。您可以透過右鍵單擊行號旁邊的裝訂區並選擇“條件斷點”來建立一個。

Conditional breakpoint

日誌點

有時您只想在程式碼命中某個位置時記錄一條訊息或值,而不是暫停。您可以使用日誌點來實現此目的。日誌點不會暫停,而是在命中時將訊息記錄到除錯控制檯。在 JavaScript 偵錯程式中,您可以使用花括號將表示式插入到訊息中,例如 current value is: {myVariable.property}

您可以透過右鍵單擊行號旁邊的裝訂區並選擇“日誌點”來建立一個。例如,這可能會記錄類似 location is /usr/local 的內容。

Logpoint

命中次數斷點

“命中次數條件”控制斷點需要命中多少次才能“中斷”執行。您可以透過右鍵單擊行號旁邊的裝訂區,選擇“條件斷點”,然後切換到“命中次數”來設定一個命中次數斷點。

Hit count breakpoint

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 認為斷點所在的位置顯示斷點。在 斷點 部分,這些斷點會顯示一個指向請求行和實際行號的箭頭。

Breakpoints View

此斷點驗證發生在會話開始並向 Node.js 註冊斷點時,或者當會話已執行時並設定了新斷點時。在這種情況下,斷點可能會“跳轉”到不同的位置。在 Node.js 解析完所有程式碼後(例如,透過執行它),可以使用 斷點 部分標題中的 重新應用 按鈕輕鬆地將斷點重新應用於請求的位置。這應該會使斷點“跳回”到請求的位置。

Breakpoint Actions

跳過不相關的程式碼

VS Code Node.js 偵錯程式具有避免執行不想單步執行的原始碼(也稱為“僅我的程式碼”)的功能。此功能可以透過啟動配置中的 skipFiles 屬性啟用。skipFiles 是要跳過的指令碼路徑的 glob 模式 陣列。

例如,使用

  "skipFiles": [
    "${workspaceFolder}/node_modules/**/*.js",
    "${workspaceFolder}/lib/**/*.js"
  ]

專案中的 node_moduleslib 資料夾中的所有程式碼都將被跳過。skipFiles 也適用於呼叫 console.log 和類似方法時顯示的位置:堆疊中第一個未跳過的位置將顯示在除錯控制檯的輸出旁邊。

Node.js 的內建核心模組可以在 glob 模式 中使用“魔術名稱” <node_internals> 來引用。以下示例跳過所有內部模組

  "skipFiles": [
     "<node_internals>/**/*.js"
   ]

確切的“跳過”規則如下

  • 如果您單步進入一個被跳過的檔案,您不會在那裡停止 - 您將在下一個未被跳過的檔案的執行行處停止。
  • 如果您設定了在丟擲異常時中斷的選項,那麼除非從跳過的檔案中丟擲的異常冒泡到非跳過的檔案中,否則您不會在這些異常處中斷。
  • 如果您在被跳過的檔案中設定了斷點,您將在該斷點處停止,並且您可以單步執行直到跳出它,此時正常的跳過行為將恢復。
  • 來自跳過檔案內部的控制檯訊息的位置將顯示為呼叫堆疊中的第一個非跳過位置。

呼叫堆疊檢視中,被跳過的源會以“變暗”的樣式顯示。

Skipped source is dimmed in call stack view

將滑鼠懸停在變暗的條目上會解釋為什麼該堆疊幀被變暗。

呼叫堆疊上的一個上下文選單項,切換跳過此檔案,使您能夠在執行時輕鬆跳過檔案,而無需將其新增到啟動配置中。此選項僅在當前除錯會話中有效。您也可以使用它來停止跳過啟動配置中 skipFiles 選項正在跳過的檔案。

注意: legacy 協議偵錯程式支援負數 glob 模式,但它們必須跟在正數模式之後:正數模式會新增到要跳過的檔案集中,而負數模式會從中減去。

在下面的(僅限 legacy 協議)示例中,除了一個“math”模組外,其他所有模組都被跳過。

"skipFiles": [
    "${workspaceFolder}/node_modules/**/*.js",
    "!${workspaceFolder}/node_modules/math/**/*.js"
]

注意: legacy 協議偵錯程式必須模擬 skipFiles 功能,因為 V8 偵錯程式協議不原生支援它。這可能導致單步執行效能緩慢。

除錯 WebAssembly

JavaScript 偵錯程式可以除錯編譯到 WebAssembly 的程式碼,前提是它包含 DWARF 除錯資訊。許多工具鏈都支援發出此資訊。

  • C/C++ with Emscripten:使用 -g 標誌進行編譯以發出除錯資訊。
  • Zig:在“Debug”構建模式下會自動發出 DWARF 資訊。
  • Rust:Rust 會發出 DWARF 除錯資訊。但是,wasm-pack 尚未在構建過程中保留它。因此,使用者在使用常見的 wasm-bindgen/wasm-pack 庫時,應手動執行以下兩個命令進行構建,而不是執行 wasm-pack build
    1. cargo install wasm-bindgen-cli 一次以安裝必要的命令列工具。
    2. cargo build --target wasm32-unknown-unknown 構建您的庫。
    3. 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++ 原始碼的斷點處停止。可以看到呼叫堆疊,其中包含從 JavaScript 程式碼到 WebAssembly 再到對映的 C++ 程式碼的幀。您還可以看到 C++ 程式碼中的變數,以及對 int32 height 變數相關聯的記憶體的編輯。

Debugger stopped on a breakpoint in C++ source code

雖然接近全面,但除錯 WebAssembly 與普通的 JavaScript 有點不同。

  • 變數檢視中的變數不能直接編輯。但是,您可以選擇變數旁邊的 檢視二進位制資料 操作來編輯其關聯的記憶體。
  • 除錯控制檯監視檢視中的基本表示式評估由 lldb-eval 提供。這與普通的 JavaScript 表示式不同。
  • 未對映到原始碼的位置將顯示在反彙編的 WebAssembly 文字格式中。對於 WebAssembly,停用源對映單步執行命令將導致偵錯程式僅在反彙編的程式碼中單步執行。

VS Code 的 WebAssembly 除錯構建於 Chromium 作者的 C/C++ 除錯擴充套件之上。

支援的類 Node.js 執行時

當前的 VS Code JavaScript 偵錯程式支援 8.x 及以上版本的 Node,以及近期版本的 Chrome 和近期版本的 Edge(透過 msedge 啟動型別)。

後續步驟

如果您還沒有閱讀 Node.js 部分,請檢視

  • Node.js - 帶有示例應用程式的端到端 Node 場景

要觀看關於 VS Code 除錯基礎知識的教程,請觀看此影片

要了解 VS Code 的任務執行支援,請訪問

  • 任務 - 使用 Gulp、Grunt 和 Jake 執行任務。顯示錯誤和警告

要編寫自己的偵錯程式擴充套件,請訪問

常見問題

是的,如果您建立了專案內資料夾的符號連結,例如使用 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.jsonruntimeArgs 屬性傳遞這些選項。

如何設定 NODE_OPTIONS?

偵錯程式使用特殊的 NODE_OPTIONS 環境變數來設定您的應用程式的除錯,覆蓋它將導致除錯無法正常工作。您應該在它後面追加而不是覆蓋它。例如,一個 .bashrc 檔案可能包含類似以下內容:

export NODE_OPTIONS="$NODE_OPTIONS --some-other-option=here"
© . This site is unofficial and not affiliated with Microsoft.