在 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设置。例如,要将节点内部添加到您的skipFiles,您可以将以下内容添加到您的用户或工作区设置:

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

自动附加智能图案

smart自动附加模式下,VS Code 将尝试附加到您的代码,而不是附加到您对调试不感兴趣的构建工具。它通过将主脚本与全局模式列表进行匹配来实现这一点。glob 模式可在debug.javascript.autoAttachSmartPattern设置中进行配置,默认为:

[
  '!**/node_modules/**', // exclude scripts in node_modules folders
  '**/$KNOWN_TOOLS$/**' // but include some common tools
];

$KNOWN_TOOLS$被替换为常见“代码运行程序”列表,例如ts-nodemochaava等。如果这些设置不起作用,您可以修改此列表。例如,要排除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 进程。您可以通过从命令面板 ( )运行“调试:创建 JavaScript 调试终端”命令,或从终端切换器下拉列表中kbs(workbench.action.showCommands)选择“创建 JavaScript 调试终端”来创建调试终端。

创建调试终端

附加配置

其他启动配置属性

您可以将launch.json 中常见的其他属性应用到debug.javascript.terminalOptions设置中的调试终端。例如,要将节点内部添加到您的skipFiles,您可以将以下内容添加到您的用户或工作区设置:

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

启动配置

启动配置是在 VS Code 中设置调试的传统方式,并为运行复杂应用程序提供最多的配置选项。

在本节中,我们将更详细地介绍更高级调试场景的配置和功能。您将找到有关使用源映射进行调试、单步执行外部代码、进行远程调试等等的说明。

如果您想观看介绍性视频,请参阅Node.js 调试入门

注意:如果您刚刚开始使用 VS Code,您可以在调试主题中了解常规调试功能和创建launch.json配置文件。

启动配置属性

调试配置存储在launch.json位于工作区.vscode文件夹中的文件中。有关调试配置文件的创建和使用的介绍,请参阅常规调试文章。

launch.json以下是特定于 Node.js 调试器的常见属性的参考。您可以在vscode-js-debug 选项文档中查看完整的选项集。

launch类型和的启动配置支持以下属性attach

这些属性仅适用于请求类型的启动配置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)。请参阅下面的节点控制台部分。
  • 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

常见场景的启动配置

您可以在文件中触发 IntelliSense ( ⌃Space (Windows、Linux Ctrl+Space )launch.json ) ,以查看常用 Node.js 调试场景的启动配置片段。

Node.js 的启动配置片段

您还可以使用编辑器窗口右下角的“添加配置...”按钮调出代码片段launch.json

添加配置按钮

以下片段可用:

  • 启动程序:以调试模式启动 Node.js 程序。
  • 通过 npm 启动:通过 npm“调试”脚本启动 Node.js 程序。如果已在 package.json 中定义,则可以使用启动配置中的 npm 调试脚本。npm 脚本中使用的调试端口必须与代码片段中指定的端口相对应。
  • Attach:附加到本地运行的 Node.js 程序的调试端口。确保要调试的 Node.js 程序已在调试模式下启动,并且使用的调试端口与代码片段中指定的端口相同。
  • Attach to Remote Program:附加到在属性指定的主机上运行的 Node.js 程序的调试端口address。确保要调试的 Node.js 程序已在调试模式下启动,并且使用的调试端口与代码片段中指定的端口相同。localRoot为了帮助 VS Code 在工作区和远程主机的文件系统之间映射源文件,请确保为和属性指定正确的路径remoteRoot
  • Attach by Process ID:打开进程选择器以选择节点或 gulp 进程进行调试。通过此启动配置,您甚至可以附加到未在调试模式下启动的节点或 gulp 进程。
  • Nodemon 设置:每当 JavaScript 源发生更改时,使用 nodemon 自动重新启动调试会话。确保您已经全局安装了nodemon。请注意,终止调试会话只会终止要调试的程序,而不是 nodemon 本身。要终止 nodemon,请在集成终端中按Ctrl+C 。
  • Mocha 测试test:在项目文件夹中调试 mocha 测试。确保您的项目在其node_modules文件夹中安装了“mocha”。
  • Yeoman 生成器:调试 yeoman 生成器。该代码片段要求您指定生成器的名称。确保您的项目在其node_modules文件夹中安装了“yo”,并且已安装生成的项目以通过npm link在项目文件夹中运行进行调试。
  • Gulp 任务:调试 gulp 任务。确保您的项目在其node_modules文件夹中安装了“gulp”。
  • Electron Main:调试 Electron 应用程序的主 Node.js 进程。该代码片段假定 Electron 可执行文件已安装在node_modules/.bin工作区目录内。

节点控制台

默认情况下,Node.js 调试会话在内部 VS Code 调试控制台中启动目标。console由于调试控制台不支持需要从控制台读取输入的程序,因此您可以通过将启动配置中的属性分别设置为 或 来启用外部终端或使用 VS Code 集成externalTerminal终端integratedTerminal。默认为internalConsole.

在外部终端中,您可以通过terminal.external.windowsExecterminal.external.osxExec、 和terminal.external.linuxExec设置来配置要使用的终端程序。

启动对“npm”和其他工具的配置支持

您可以直接从启动配置使用“npm”脚本或其他任务运行程序工具,而不是直接使用节点启动 Node.js 程序:

  • 您可以使用 PATH 上可用的任何程序(例如“npm”、“mocha”、“gulp”等)作为属性,runtimeExecutable并且参数可以通过runtimeArgs.
  • program如果您的 npm 脚本或其他工具隐式指定要启动的程序,则不必设置该属性。

让我们看一个“npm”示例。如果您package.json有一个“调试”脚本,例如:

  "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 版本,因为该功能不会自动下载并安装该版本。例如,如果您打算添加到启动配置中,则必须从集成终端运行类似nvm install 7.10.1或 的命令。nvs add 7.10.1"runtimeVersion": "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

让我们详细了解这些选项:

附加到节点处理操作

命令面板中的附加到节点进程命令( ⇧⌘P (Windows、Linux Ctrl+Shift+P ) ) 将打开一个快速选择菜单,其中列出了 Node.js 调试器可用的所有潜在进程:

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-brk12345--inspect=12345--inspect-brk=12345port

要附加到尚未在调试模式下启动的 Node.js 进程,可以通过将 Node.js 进程的进程 ID 指定为字符串来执行此操作:

{
  "name": "Attach to Process",
  "type": "node",
  "request": "attach",
  "processId": "53426"
}

为了避免在启动配置中重复输入新的进程 ID,Node debug 支持一个命令变量PickProcess,该变量将打开进程选择器(从上面)。

使用PickProcess变量启动配置如下所示:

{
  "name": "Attach to Process",
  "type": "node",
  "request": "attach",
  "processId": "${command:PickProcess}"
}

停止调试

使用“调试:停止”操作(可在“调试”工具栏中或通过“命令面板”使用)停止调试会话。

如果调试会话以“附加”模式启动(并且调试工具栏中的红色终止按钮显示叠加的“插头”),则按“停止”会断开Node.js调试器与被调试对象的连接,然后继续执行。

如果调试会话处于“启动”模式,按“停止”将执行以下操作:

  1. 当第一次按下“停止”按钮SIGINT时,调试器会被请求通过发送信号来正常关闭。调试者可以自由地拦截该信号并根据需要清理任何内容,然后关闭。如果该关闭代码中没有断点(或问题),则调试对象和调试会话将终止。

  2. 但是,如果调试器在关闭代码中遇到断点,或者调试对象本身没有正确终止,则调试会话将不会结束。在这种情况下,再次按“停止”将强制终止调试对象及其子进程 ( SIGKILL)。

如果您发现按红色“停止”按钮后调试会话没有结束,请再次按该按钮以强制关闭调试对象。

在 Windows 上,按“停止”会强制终止调试对象及其子进程。

源地图

VS Code 的 JavaScript 调试器支持源映射,有助于调试转译语言,例如 TypeScript 或缩小/丑化的 JavaScript。使用源映射,可以单步执行原始源代码或在原始源代码中设置断点。如果原始源不存在源映射,或者源映射已损坏并且无法在源和生成的 JavaScript 之间成功映射,则断点显示为未经验证(灰色空心圆圈)。

sourceMaps默认true控制源地图要素的属性。调试器始终尝试使用源映射(如果可以找到任何源映射),因此,您甚至可以使用该属性指定源文件(例如 app.ts)program。如果出于某种原因需要禁用源映射,可以将该sourceMaps属性设置为false

工具配置

由于源映射并不总是自动创建,因此您应该确保配置转换器来创建它们。例如:

TypeScript

--sourceMap对于 TypeScript,您可以通过传递tsc或添加"sourceMap": true到 tsconfig.json 文件来启用源映射。

tsc --sourceMap --outDir bin app.ts

巴别塔

对于 Babel,您需要将sourceMaps选项设置为true,或者--source-maps在编译代码时传递该选项。

npx babel script.js --out-file script-compiled.js --source-maps

网页包

Webpack 有许多源映射选项。devtool: "source-map"我们建议您设置该属性webpack.config.js以获得最佳的结果保真度,尽管您可以尝试其他设置,但这些设置会导致构建速度减慢。

此外,如果您在 webpack 中有其他编译步骤(例如使用 TypeScript 加载器),您还需要确保将这些步骤设置为生成源映射。否则,webpack 生成的源映射将映射回加载器的已编译代码,而不是真正的源。

源地图发现

默认情况下,VS Code 将搜索整个工作区(不包括node_modules)以查找源映射。在大型工作空间中,此搜索可能会很慢。outFiles您可以通过在 .config 文件中设置属性来配置 VS Code 搜索源映射的位置launch.json。例如,此配置将仅发现文件夹.js中文件的源映射bin

{
  "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设置该属性后,VS Code 在调试器中单步执行代码时将自动跳过“无趣的代码”。true“无趣代码”是由转译过程生成但未被源映射覆盖的代码,因此它不会映射回原始源。当在调试器中单步执行源代码时,此代码会妨碍您,因为它使调试器在原始源代码和您不感兴趣的生成代码之间切换。将自动单步执行源映射未覆盖的代码,直到smartStep到达再次被源地图覆盖的位置。

智能单步对于 TypeScript 中的异步/等待向下编译等情况特别有用,在这种情况下,编译器会注入源映射未涵盖的帮助程序代码。

smartStep功能仅适用于从源代码生成并因此具有源映射的 JavaScript 代码。对于没有源代码的 JavaScript,智能单步选项不起作用。

JavaScript 源地图提示

使用源映射进行调试时的一个常见问题是您设置了一个断点,它会变成灰色。如果将光标悬停在其上,您将看到消息"Breakpoint ignored because generated code not found (source map problem?)"。现在怎么办?有一系列问题可能导致这种情况。首先,快速解释一下 Node 调试适配器如何处理源映射。

当您在 中设置断点时app.ts,调试适配器必须找出 的路径app.js,即 TypeScript 文件的转译版本,它是 Node 中实际运行的文件。但是,没有一种直接的方法可以从.ts文件开始解决这个问题。相反,调试适配器使用outFiles中的属性来launch.json查找所有已转译的.js文件,并将它们解析为源映射,其中包含其关联.ts文件的位置。

当您在app.ts启用源映射的情况下在 TypeScript 中构建文件时,它会生成一个app.js.map文件,或者生成一个源映射,该源映射作为 base64 编码字符串内联在文件底部的注释中app.js。为了查找.ts与此映射关联的文件,调试适配器会查看源映射中的两个属性,sourcessourceRootsourceRoot是可选的 - 如果存在,它会被添加到 中的每个路径之前sources,这是一个路径数组。结果是文件的绝对或相对路径的数组.ts。相对路径是相对于源映射解析的。

app.ts最后,调试适配器在此结果文件列表中搜索完整路径.ts。如果存在匹配,则它已找到映射app.tsapp.js. 如果没有匹配,那么它就不能绑定断点,并且它会变成灰色。

当断点变成灰色时,可以尝试以下一些操作:

  • 调试时,运行“调试:诊断断点问题”命令。此命令将打开一个工具,该工具可以提供提示来帮助您解决命令面板中的任何问题 ( ⇧⌘P (Windows、Linux Ctrl+Shift+P ) )。
  • 您是否在启用源映射的情况下进行构建?确保文件.js.map中有文件或内联源映射.js
  • sourceRoot您的源映射中的和属性是否sources正确?可以将它们组合起来以获得文件的正确路径.ts吗?
  • 您是否在 VS Code 中打开了大小写不正确的文件夹?可以foo/从命令行打开文件夹code FOO,在这种情况下源映射可能无法正确解析。
  • 尝试在 Stack Overflow 上搜索有关您的特定设置的帮助或在 GitHub 上提交问题。
  • 尝试添加一个debugger声明。如果它破坏了.ts那里的文件,但该位置的断点没有绑定,那么这是包含在 GitHub 问题中的有用信息。

远程调试

注意: 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 从工作区打开可编辑源代码,则可以在远程位置和本地位置之间设置映射。AlocalRoot和 aremoteRoot属性可用于映射本地 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.js 终止后自动尝试重新连接到 Node.js。

如果您已在命令行上server.js通过nodemon启动程序,如下所示:

nodemon --inspect server.js

您可以使用以下启动配置将 VS Code 调试器附加到它:

{
  "name": "Attach to node",
  "type": "node",
  "request": "attach",
  "restart": true,
  "port": 9229
}

或者,您可以使用启动配置直接server.js通过nodemon启动程序并附加 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为了避免这种情况,您可以通过添加具有较大值(以毫秒为单位)的属性来增加超时。

重启帧

节点调试器支持在堆栈帧处重新启动执行。当您在源代码中发现问题并且想要使用修改后的输入值重新运行一小部分代码时,这可能很有用。停止然后重新启动完整的调试会话可能非常耗时。使用“设置值”操作更改变量后,“重新启动框架”操作允许您重新进入当前函数

重启帧

重新启动框架不会将突变回滚到函数外部的状态,因此它可能并不总是按预期工作。

断点

条件断点

条件断点是仅在表达式返回真值时暂停的断点。您可以通过右键单击行号旁边的装订线并选择“条件断点”来创建断点:

条件断点

日志点

有时,您只想在代码到达某个位置时记录消息或值,而不是暂停。您可以使用日志点来做到这一点。日志点不会暂停,而是在命中时将消息记录到调试控制台。在 JavaScript 调试器中,您可以使用花括号将表达式插入到消息中,例如current value is: {myVariable.property}.

您可以通过右键单击行号旁边的装订线并选择“日志点”来创建一个。例如,这可能会记录类似以下内容location is /usr/local

日志点

断点命中计数

“命中计数条件”控制在“中断”执行之前需要命中断点的次数。您可以通过右键单击行号旁边的装订线,选择“条件断点”,然后切换到“命中计数”来放置命中计数断点。

命中计数断点

<Node.js 调试器支持的命中计数语法可以是整数,也可以是运算符, <=, ==, >,之一>=%后跟一个整数。

一些例子:

  • >10总是在 10 次点击后中断
  • <3仅在前两次点击时中断
  • 10与...一样>=10
  • %2打破所有其他打击

断点验证

出于性能原因,Node.js 在首次访问时会延迟解析 JavaScript 文件内的函数。因此,断点在 Node.js 未见过(解析)的源代码区域中不起作用。

由于此行为不适合调试,因此 VS Code 会--nolazy自动将该选项传递给 Node.js。这可以防止延迟解析并确保可以在运行代码之前验证断点(因此它们不再“跳转”)。

由于该--nolazy选项可能会显着增加调试目标的启动时间,因此您可以通过传递 a--lazy作为runtimeArgs属性轻松选择退出。

这样做时,您会发现某些断点不会“坚持”到所请求的行,而是“跳转”到已解析的代码中的下一个可能的行。为了避免混淆,VS Code 始终在 Node.js 认为断点所在的位置显示断点。在BREAKPOINTS部分中,这些断点在请求行号和实际行号之间用箭头显示:

断点视图

当会话启动并且断点已在 Node.js 中注册时,或者当会话已在运行并且设置了新断点时,会发生此断点验证。在这种情况下,断点可能“跳”到不同的位置。Node.js 解析了所有代码(例如,通过运行它)后,可以使用BREAKPOINTS部分标题中的“重新应用”按钮轻松地将断点重新应用到请求的位置。这应该使断点“跳回”到请求的位置。

断点动作

跳过无趣的代码

VS Code Node.js 调试具有避免您不想单步执行的源代码的功能(也称为“仅我的代码”)。可以使用skipFiles启动配置中的属性启用此功能。是要跳过的脚本路径的全局模式skipFiles数组。

例如,使用:

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

项目中node_modules和文件夹中的所有代码都将被跳过。libskipFiles也适用于调用和类似方法时显示的位置console.log:堆栈中的第一个非跳过位置将显示在调试控制台的输出旁边。

Node.js 的内置核心模块可以通过glob 模式<node_internals>中的“魔法名称”来引用。以下示例跳过所有内部模块:

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

确切的“跳过”规则如下:

  • 如果您进入跳过的文件,您不会停在那里 - 您将停在不在跳过的文件中的下一个执行行处。
  • 如果您已设置在引发异常时中断的选项,则不会在跳过文件引发的异常上中断,除非它们冒泡到非跳过文件中。
  • 如果在跳过的文件中设置断点,您将在该断点处停止,并且您将能够单步执行它,直到跳出它,此时将恢复正常的跳过行为。
  • 来自跳过文件内部的控制台消息的位置将显示为调用堆栈中的第一个非跳过位置。

跳过的源在 CALL STACK 视图中以“灰色”样式显示:

跳过的源在调用堆栈视图中呈灰色显示

将鼠标悬停在变暗的条目上可以解释堆栈帧变暗的原因。

调用堆栈上的上下文菜单项“切换跳过此文件”使您可以在运行时轻松跳过文件,而无需将其添加到启动配置中。此选项仅在当前调试会话中持续存在。skipFiles您还可以使用它来停止跳过启动配置中的选项跳过的文件。

注意:协议legacy调试器支持负全局模式,但它们必须遵循正模式:正模式添加到跳过的文件集中,而负模式从该集中减去。

在下面的(legacy仅协议)示例中,除了“数学”模块之外的所有模块都被跳过:

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

注意:协议legacy调试器必须模拟该skipFiles功能,因为V8 调试器协议本身并不支持它。这可能会导致步进性能缓慢。

调试 WebAssembly

如果 JavaScript 调试器包含DWARF调试信息,则可以调试编译到 WebAssembly 中的代码。许多工具链支持发出此信息:

  • 使用 Emscripten 的 C/C++:使用标志进行编译-g以发出调试信息。
  • Zig:DWARF 信息在“调试”构建模式下自动发出。
  • Rust:在撰写本文时不受支持,本期跟踪支持

构建代码后,您需要安装WebAssembly DWARF 调试扩展。它作为单独的扩展提供,以保持 VS Code 核心的“精简”。安装后,重新启动任何活动的调试会话,然后本机代码应该映射到调试器中!您应该看到您的源代码出现在“已加载源”视图中,并且断点应该可以工作。

在下图中,调试器在创建 Mandelbrot 分形的 C++ 源代码中的断点处停止。调用堆栈是可见的,包括从 JavaScript 代码到 WebAssembly,再到映射的 C++ 代码的框架。您还可以查看 C++ 代码中的变量,以及对与 int32height变量关联的内存的编辑。

调试器在 C++ 源代码中的断点处停止

虽然接近同等,但调试 WebAssembly 与普通 JavaScript 略有不同:

  • 变量视图中的变量无法直接编辑。但是,您可以选择变量旁边的“查看二进制数据”操作来编辑其关联的内存。
  • 调试控制台监视视图中的基本表达式评估由lldb-eval提供。这与普通的 JavaScript 表达式不同。
  • 未映射到源代码的位置将以反汇编的 WebAssembly 文本格式显示。对于 WebAssembly,命令“禁用源映射单步执行”将导致调试器仅单步执行反汇编代码。
  • WebAssembly 代码中的断点是异步解析的,因此可能会错过程序生命周期早期遇到的断点。未来有计划解决这个问题。如果您在浏览器中进行调试,则可以刷新页面以使断点生效。如果您使用 Node.js,则可以在加载 WebAssembly 模块之后但到达所需断点之前添加人为延迟或设置另一个断点。

VS Code 的 WebAssembly 调试基于Chromium 作者的C/C++ 调试扩展构建。

支持的类似 Node 的运行时

当前的 VS Code JavaScript 调试器支持 8.x 或更高版本的 Node 版本、最新的 Chrome 版本和最新的 Edge 版本(通过启动msedge类型)。

下一步

如果您还没有阅读 Node.js 部分,请查看:

  • Node.js - 带有示例应用程序的端到端 Node 场景

要查看有关 Node.js 调试基础知识的教程,请观看以下视频:

要了解 VS Code 的任务运行支持,请访问:

  • 任务- 使用 Gulp、Grunt 和 Jake 运行任务。显示错误和警告

要编写您自己的调试器扩展,请访问:

  • 调试器扩展- 从模拟示例开始创建 VS Code 调试扩展的步骤

常见问题

是的,如果您已经为项目内的文件夹创建了符号链接(例如使用 )npm link,则可以通过告诉 Node.js 运行时保留符号链接路径来调试符号链接源。在启动配置属性中使用 node.exe--preserve-symlinks 开关runtimeArgsruntimeArgs,一个字符串数组,被传递到调试会话运行时可执行文件,默认为node.exe。

{
  "runtimeArgs": ["--preserve-symlinks"]
}

如果您的主脚本位于符号链接路径内,那么您还需要添加该"--preserve-symlinks-main"选项。此选项仅在 Node 10+ 中可用。

如何调试 ECMAScript 模块?

如果您使用 esm 或传递--experimental-modules给 Node.js 以便使用 ECMAScript 模块,则可以通过 的runtimeArgs属性传递这些选项launch.json

如何设置 NODE_OPTIONS?

调试器使用特殊的NODE_OPTIONS环境变量来设置应用程序的调试,覆盖它会阻止调试正常工作。您不应覆盖它,而应附加到它。例如,一个.bashrc文件可能有这样的内容:

export NODE_OPTIONS="$NODE_OPTIONS --some-other-option=here"