Node.js VS Code 中的调试

Visual Studio Code 编辑器内置了Node.js运行时的调试支持,可以调试 JavaScript、TypeScript 以及许多转译成 JavaScript 的语言。设置Node.js调试项目非常简单,VS Code 提供了合适的启动配置默认值和片段。

你可以用 VS Code 调试Node.js程序:

自动连接

如果启用了自动连接功能,节点调试器会自动连接到从 VS Code 集成终端启动的某些Node.js进程。要启用此功能,可以使用命令面板中的“切换自动附加”命令(Windows,Linux Ctrl+Shift+P),或者如果已激活,使用自动附加状态栏项。

自动附加有三种模式,你可以在快速选择中选择,并通过debug.javascript.autoAttachFilter设置来选择:

  • 聪明- 如果你执行了超出你node_modules或者使用常见的“运行”脚本,如 mocha 或 ts-node,过程会被调试。你可以用自动连接智能图样设置配置“runner”脚本允许列表(debug.javascript.autoAttachSmartPattern).
  • 永远- 在集成终端中启动的所有Node.js进程将被调试。
  • 只有WithFlag- 只有以——检查--检查-BRK该标志将被调试。

启用自动连接后,你需要点击⚠终端右上角的图标重启终端,或者直接创建一个新的。然后,调试器应该会在一秒内连接到你的程序:

自动连接

当自动连接开启时,自动连接该项目会出现在VS代码窗口底部的状态栏中。点击它可以切换自动连接模式,或者暂时关闭。如果你运行一些不需要调试的单次程序,但又不想完全禁用自动连接功能,暂时关闭自动连接很有用。

附加配置

其他启动配置属性

你可以在debug.javascript.terminalOptions设置中应用launch.json中通常能找到的其他属性自动附加。例如,要向 skipFiles 添加节点内部结构,你可以在用户或工作区设置中添加以下内容:

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

自动连接智能图案

聪明自动连接模式,VS Code 会尝试附加到你的代码上,而不是附加到你不想调试的构建工具上。它通过将主文字与一组球状图案列表匹配来实现这一点。glob 图案可在 debug.javascript.autoAttachSmartPattern 设置中配置,默认为:

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

$KNOWN工具$被一个常见的“代码运行器”列表所取代,例如TS节点,摩卡,艾娃,依此类推。如果这些设置不行,你可以修改这个列表。例如,排除摩卡包括我的酷测试跑者,你可以添加两条线:

[
  '!**/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)),或通过终端切换器下拉菜单选择创建JavaScript调试终端

创建调试终端

附加配置

其他启动配置属性

你还可以在debug.javascript.terminalOptions设置中应用launch.json中通常存在的其他属性。例如,要向 skipFiles 添加节点内部结构,你可以在用户或工作区设置中添加以下内容:

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

发射配置

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

在本节中,我们将更详细地介绍更高级调试场景的配置和功能。你会找到关于用源映射调试、跨越外部代码远程调试等多种作的说明。

如果你想看入门视频,可以看《VS Code 调试入门》。

注意:如果你刚开始学习 VS Code,可以学习通用的调试功能和创建launch.json调试主题中的配置文件。

发射配置属性

调试配置存储在launch.json文件位于你工作区.vscode文件夹。关于调试配置文件的创建和使用介绍见一般的调试文章。

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

以下属性在 类型的启动配置中支持。发射以及附着:

这些属性仅适用于请求类型的启动配置发射:

  • 节目- Node.js程序的绝对路径进行调试。
  • args- 传递给程序调试的参数。该属性类型为数组,期望单个参数作为数组元素。
  • 慢性消耗病- 在该目录中启动程序进行调试。
  • runtime可执行文件- 运行时可执行程序的绝对路径。默认是节点.参见“启动配置支持”npm“及其他工具的部分。
  • runtimeArgs- 传递给运行时可执行文件的可选参数。
  • runtime版本- 如果使用“NVM”(或“NVM-Windows”)或“NVS”来管理Node.js版本,则该属性可用于选择Node.js的特定版本。详见下方多版本支持部分。
  • 环境- 可选环境变量。该属性期望环境变量作为字符串类型键值对的列表。
  • envFile- 包含环境变量定义的文件的可选路径。请参见下方“从外部文件加载环境变量”部分。
  • 控制台- 用于启动程序的控制台(内部控制台,integratedTerminal,外部终端).详见下方节点控制台章节。
  • 输出捕获- 如果设置为性病进程 stdout/stderr 的输出会显示在调试控制台中,而不是监听通过调试端口的输出。这对于直接写入 stdout/stderr 流的程序或日志库非常有用,而不是使用控制台。*API。

该属性仅适用于请求类型的启动配置附着:

  • 重启- 在终止连接时重启连接。参见“自动重启调试会话”部分。
  • 港口- 调试端口。参见“附加到Node.js远程调试”章节。
  • 地址- 调试端口的TCP/IP地址。参见“附加到Node.js远程调试”章节。
  • processID- 调试器在发送USR1信号后尝试附加该进程。使用此设置,调试器可以附加到尚未在调试模式下启动的已运行进程。当使用processID调试端口根据Node.js版本(及所用协议)自动确定,无法显式配置。所以不要指定港口属性。
  • 继续OnAttach。- 如果连接时暂停,是否继续该过程。如果你启动程序时,这个选项非常有用--检查-BRK.

常见场景的发射配置

你可以在你的 launch.json文件用于查看常见Node.js调试场景的启动配置片段。

启动配置片段用于Node.js

你也可以在launch.json编辑器窗口。

添加配置按钮

以下片段可供查阅:

  • 启动程序:在调试模式下启动Node.js程序。
  • 通过npm启动:通过npm“调试”脚本启动Node.js程序。如果你的package.json里已经定义了启动配置中的npm调试脚本,可以用它。npm脚本中使用的调试端口必须对应于摘要中指定的端口。
  • 附加:连接到本地运行的Node.js程序的调试端口。确保调试Node.js程序已在调试模式下启动,且使用的调试端口与摘要中指定的端口相同。
  • 附加到远程程序:Node.js连接到运行在由地址属性。确保调试Node.js程序已在调试模式下启动,且使用的调试端口与摘要中指定的端口相同。为了帮助 VS Code 在你的工作区和远程主机的文件系统之间映射源文件,务必指定正确的路径localRoot(本地根)以及远程根属性。
  • 通过进程ID添加:打开进程选择器以选择节点或gulp进程进行调试。通过这个启动配置,你甚至可以连接到未在调试模式下启动的节点或 gulp 进程。
  • Nodemon 设置:当 JavaScript 源代码发生变化时,使用 nodemon 自动重新启动调试会话。确保你全局安装了Nodemon。注意,终止调试会话只会终止调试程序,而不会终止 nodemon 本身。要终止 nodemon,请在集成终端按 Ctrl+C
  • Mocha测试:调试Mocha测试中的测试你的项目文件夹。确保你的项目里安装了“摩卡”功能node_modules文件夹。
  • Yeoman 生成器:调试 yeoman 生成器。片段要求你指定生成器的名称。确保你的项目里安装了“yo”这个node_modules并且你生成的项目已安装用于调试,运行时NPM链接在项目文件夹里。
  • 吞咽任务:调试吞咽任务。确保你的项目安装了“gulp”(gulp)这个功能node_modules文件夹。
  • 电子主:调试电子应用的主要Node.js过程。该摘要假设Electron可执行文件已安装在node_modules/.bin工作空间目录。

节点控制台

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

在外部终端中,你可以通过terminal.external.windowsExec,terminal.external.osxExec(终端.external.osxExec), 和terminal.external.linuxExec设定。

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

你可以不用 node 直接启动 Node.js 程序,而是直接从 启动配置使用 'npm' 脚本或其他任务执行工具:

  • 你可以使用PATH上任何可用的程序(例如“npm”、“mocha”、“gulp”等)来实现runtime可执行文件属性和参数可以通过以下方式传递runtimeArgs.
  • 你不必设置节目属性,如果你的 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版本,可以指定一个runtime版本在启动配置中选择特定版本Node.js属性:

{
  "type": "node",
  "request": "launch",
  "name": "Launch test",
  "runtimeVersion": "14",
  "program": "${workspaceFolder}/test.js"
}

如果你用“nvs”来管理Node.js版本,可以用runtime版本属性以选择特定版本、架构和风味 Node.js,例如:

{
  "type": "node",
  "request": "launch",
  "name": "Launch test",
  "runtimeVersion": "chackracore/8.9.4/x64",
  "program": "${workspaceFolder}/test.js"
}

Node.js确保安装了你想和runtime版本属性,因为该功能不会自动下载和安装版本。例如,你需要运行类似的程序NVM 安装 7.10.1NVS Add 7.10.1如果你打算添加,可以从集成终端“runtimeVersion”: “7.10.1”切换到你的发射配置。

如果你省略了小版本和补丁版本,并且例如,“runtimeVersion”: “14”,然后是最近的14.x.y安装在你系统上的版本将被使用。

从外部文件加载环境变量

VS Code 节点调试器支持从文件加载环境变量并传递到Node.js运行时。使用此功能时,需添加一个属性envFile并指定包含环境变量的文件的绝对路径:

   //...
   "envFile": "${workspaceFolder}/.env",
   "env": { "USER": "john doe" }
   //...

环境字典会覆盖从文件加载的变量。

这里有一个例子.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进程外,选拔器还会显示以各种形式启动的其他程序——检查参数。这使得它可以附加到 Electron 或 VS Code 的辅助进程。

设置“附加”配置

这个选项需要更多工作,但与前面两个选项不同,它允许你显式配置各种调试配置选项。

最简单的“附加”配置如下:

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

港口9229是 的默认调试端口——检查以及--检查-BRK选项。使用不同的端口(例如)12345),像这样添加到选项中:--inspect=12345以及--检查-brk=12345并更改港口在启动配置中设置属性以匹配。

要附加到尚未在调试模式下启动的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调试器与调试器之间的连接,调试器随后继续执行。

如果调试会话处于“启动”模式,按停止键可以做以下作:

  1. 当首次按下停止按钮时,调试器会被请求通过发送信号情报信号。调试设备可以自由截获该信号并根据需要清理,然后关闭。如果关闭代码中没有断点(或问题),调试器和调试会话将终止。

  2. 然而,如果调试器在关机代码中遇到断点,或者调试器未能自行正确终止,则调试会话不会结束。此时,再次按下停止键将强制终止调试程序及其子进程(西格基尔).

如果你发现按红色停止按钮时调试会话没有结束,那就再按一次按钮强制关闭调试设备。

在Windows上,按下停止键会强制终止调试程序及其子进程。

资料来源地图

VS Code 的 JavaScript 调试器支持源映射,帮助调试转译语言,例如 TypeScript 或缩小/丑化的 JavaScript。使用源映射时,可以单步穿越或在原始源中设置断点。如果原始源码没有源映射,或者源映射失效且无法成功映射源码与生成的JavaScript,断点就会显示为未验证(灰色空心圆圈)。

资料来源地图默认为确实如此控制源地图功能。调试器总是尝试使用源映射(如果能找到的话),因此你甚至可以指定一个源文件(例如app.ts),并附带节目属性。如果你因为某些原因需要禁用源映射,你可以设置资料来源地图归属为错误.

工具配置

由于源映射并不总是自动生成的,你应该确保配置你的转译器来创建它们。例如:

TypeScript

对于TypeScript,你可以通过传递来启用源映射--来源地图TSC,或通过添加“sourceMap”:真在你的tsconfig.json档案里。

tsc --sourceMap --outDir bin app.ts

巴别塔

对于《巴别塔》,你需要把 sourceMaps 选项设置为确实如此,或传递--源地图编译代码时的选项。

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

Webpack

Webpack 有多种源码映射选项。我们建议设置该物业开发工具:“源地图”在你的webpack.config.js为了获得最佳的画质,虽然你可以尝试其他设置,但这会导致你的构建变慢。

另外,如果你在webpack中有额外的编译步骤,比如使用TypeScript加载器,你也要确保这些步骤已经设置好生成sourcemap。否则,webpack 生成的源码映射会映射到加载器编译后的代码,而不是真实源码。

源地图发现

默认情况下,VS Code 会搜索你的整个工作区,排除node_modules,用于源图。在大型工作区中,这种搜索可能会比较慢。你可以通过设置outFiles属性在你的launch.json.例如,该配置只会发现 的源图.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选项。如果设置为无效,每个源映射都会被解析。例如,这种配置还会允许在node_modules/某种依赖待解决:

  "resolveSourceMapLocations": [
    "out/**/*.js",
    "node_modules/some-dependency/**/*.js",
  ]

智能步进

smartStep属性设置为确实如此在启动配置中,VS Code 在调试器中逐步处理代码时会自动跳过“无趣代码”。“无趣代码”是指由转编过程生成但未被源映射覆盖的代码,因此无法映射回原始源代码。这些代码在调试器中逐步处理源代码时会成为障碍,因为它会让调试器在原始源代码和你不感兴趣的生成代码之间切换。smartStep会自动逐步穿过源地图未覆盖的代码,直到再次到达源地图覆盖的位置。

智能步进在TypeScript中的异步/等待下编译等情况下尤其有用,这时编译器注入的辅助代码未被源映射覆盖。

smartStep功能仅适用于源代码生成的JavaScript代码,因此具有源映射。对于没有源代码的JavaScript,智能步进选项没有效果。

JavaScript 源代码映射技巧

调试源映射时常见的问题是,你设置断点后断点会变成灰色。如果你把光标悬停在上面,你会看到这条信息,“断点被忽略,因为生成代码未被找到(源映射问题?)”.接下来怎么办?导致这种情况的原因有很多。首先,简要说明一下 Node 调试适配器如何处理源映射。

当你在 中设置断点时app.ts调试适配器必须确定路径到app.js,是你TypeScript文件的转译版本,实际上是在Node中运行的。但是,从以下情况开始,没有直接的方法来确定这一点.ts档案。相反,调试适配器使用outFiles属性launch.json以查找所有转译的.js文件,并解析出源地图,源地图包含其关联的位置.ts文件。

当你建造你的app.ts在TypeScript中启用源映射的文件,它要么生成一个app.js.map文件,或者在注释底部以base64编码字符串形式内嵌的源映射app.js档案。要找到.ts与该映射关联的文件,调试适配器会查看源映射中的两个属性,资料来源, 和来源.来源是可选的——如果存在,则在每个路径前加它。资料来源,这是一个路径数组。结果是一个绝对或相对路径的数组.ts文件。相对路径相对于源地图进行解析。

最后,调试适配器会搜索 的完整路径app.ts在该列表中.ts文件。如果匹配,说明它找到了用于映射时使用的源映射文件app.tsapp.js.如果没有匹配,断点就无法绑定,断点会变成灰色。

当断点变灰时,以下是一些可以尝试的方法:

  • 调试时,运行“调试:诊断断点问题”命令。该命令会弹出一个工具,提供提示帮助你解决命令面板中的问题(⇧⌘P(Windows,Linux Ctrl+Shift+P)。
  • 你是开启源映射构建的吗?确保有.js.map文件,或者在你的.js文件。
  • 来源以及资料来源你的源地图中的属性,对吗?它们能否组合起来,获得正确的路径.ts档案?
  • 你有没有用错误的大小写打开过VS Code的文件夹?可以打开文件夹福/从命令行中像代码FOO在这种情况下,源映射可能无法正确解析。
  • 试着在 Stack Overflow 上搜索针对你具体配置的帮助,或者在 GitHub 上提交相关问题。
  • 试着加一个调试器陈述。如果它被打入了.ts文件放在那里,但该处的断点不会绑定,这在GitHub问题中是有用的信息。

覆盖源映射路径

调试器使用来源MapPathOverrides实现自定义的源图到磁盘路径映射。大多数工具都有良好的默认设置,但在高级情况下可能需要自定义。默认路径覆盖的对象映射如下:

{
  'webpack:///./~/*': "${workspaceFolder}/node_modules/*",
  'webpack:////*': '/*',
  'webpack://@?:*/?:*/*': "${workspaceFolder}/*",
  // and some more patterns...
}

它将源地图中的路径或URL从左向右映射。图案?:*是非贪婪、非吃子的匹配,也是贪婪吃子匹配。调试器随后将右侧模式中的对应节点替换为从源映射路径捕获的片段。例如,上述示例中的最后一个模式将映射**webpack://@my/package/foo/bar${workspaceFolder}/foo/bar.

注意,对于浏览器调试,以下内容web根用来替代workspaceFolder默认情况下来源MapPathOverrides.

远程调试

注:VS Code 现在具备了通用的远程开发功能。使用远程开发扩展,Node.js在远程场景和容器中的开发与本地Node.js开发无异。这是推荐的远程调试程序Node.js方法。查看入门部分和远程教程了解更多。

如果你无法使用任何远程开发扩展来调试Node.js程序,下面有一份关于如何从本地VS Code实例调试远程Node.js程序的指南。

Node.js调试器支持远程调试,即将进程附加到运行在不同机器或容器中的进程。通过地址属性。例如:

{
  "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(本地根)以及一个远程根属性可用于映射本地 VS Code 项目与(远程)Node.js 文件夹之间的路径。即使在同一系统本地或跨不同作系统上也能实现。每当需要将代码路径从远程 Node.js 文件夹转换为本地 VS 代码路径时,远程根路径被剥离路径,替换为localRoot(本地根).对于反向换算,则localRoot(本地根)路径被替换为远程根.

{
  "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 文件浏览轻松定位和打开,你可以通过运行和调试视图中的 LOADED SCRIPTS 视图访问已加载的脚本:

加载脚本资源管理器

LOADED SCRIPTS 视图允许你通过输入脚本名称快速选择脚本,或在启用 Filter on Type 时过滤列表。

脚本加载到只读编辑器中,你可以在那里设置断点。这些断点会在调试会话中被记住,但你只能在调试会话运行时访问脚本内容。

当源代码被编辑时,自动重启调试会话

重启启动配置的属性控制Node.js调试器是否在调试会话结束后自动重启。如果你用nodemon在文件更改时重启Node.js,这个功能很有用。设置启动配置属性重启确实如此让节点调试器在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 秒后)放弃。为了避免这种情况,可以通过添加暂停属性值更大(以毫秒计)。

重启帧

节点调试器支持在栈帧处重启执行。这在你发现源代码存在问题,想用修改过的输入值重跑一小部分代码时非常有用。停止然后重启整个调试会话可能会耗时。重启框架动作允许你在通过设置值作更改变量后重新输入当前函数:

重启帧

Restart Frame 不会将变异回滚到函数外的状态,所以可能并不总是如预期般工作。

断点

条件断点

条件断点是指只有当表达式返回真实值时才会暂停的断点。你可以在边框中右键点击行号旁的断点,选择“条件断点”来创建断点:

条件断点

日志点

有时候你只想在代码到达某个位置时记录消息或值,而不是暂停。你可以用日志点来实现这一点。日志点不会暂停,而是在被触发时将消息记录到调试控制台。在JavaScript调试器中,你可以用大括号插入表达式,比如当前值为:{myVariable.property}.

你可以在排水沟里右键点击行号旁边,选择“Logpoint”来创建一个。例如,这可能会记录类似的内容地点是 /USR/local:

Logpoint(对点)

命中计数断点

“命中计数条件”控制断点需要被击中多少次才能“破坏”执行。你可以在页面右键点击行号旁的行号,选择“条件断点”,然后切换到“命中计数”来放置命中断点。

命中计数断点

Node.js调试器支持的命中计数语法要么是整数,要么是运算符 , , , , ,后跟整数。<<===>>=%

举几个例子:

  • >10每次击中10次后都要断开
  • <3只有前两击才断开
  • 10同一个>=10
  • %2每隔一击就断一次

触发断点

触发断点是指一旦触发另一个断点时自动启用的断点。它们在诊断仅在某个前提条件之后才发生的代码故障时非常有用。

触发断点可以通过右键点击字形边缘,选择添加触发断点,然后选择启用该断点的其他断点来设置。

断点验证

出于性能考虑,Node.js 在首次访问时懒惰地解析 JavaScript 文件中的函数。因此,断点在Node.js未被解析过的源代码区域无法使用。

由于这种行为对调试来说并不理想,VS Code 会传递——诺拉西自动Node.js选项。这防止了解析延迟,并确保断点在运行代码前能被验证(从而不再“跳跃”断点)。

自从......——诺拉西选项可能会显著增加调试目标的启动时间,你可以通过传递——懒惰作为runtimeArgs属性。

这样做时,你会发现有些断点没有“粘”在请求的行上,而是“跳转”到已经解析过的代码中下一个可能的行。为避免混淆,VS Code总是显示断点的位置Node.js认为断点的位置。在断点部分,这些断点用箭头表示,连接请求的和实际行号:

断点视图

当会话开始且断点被Node.js注册,或会话已运行且新断点被设置时,这种断点验证就会发生。在这种情况下,断点可能会“跳跃”到另一个位置。在Node.js解析完所有代码(例如通过运行代码)后,可以通过BREAKPOINTS部分头部的重新应用按钮轻松地将断点重新应用到请求的位置。这样断点应该会“跳回”请求的位置。

断点动作

跳过无趣代码

VS Code Node.js调试有一个功能,可以避免你不想逐一通过的源代码(也称为“Just My Code”)。此功能可以通过以下方式启用skip文件属性在你的启动配置中。skip文件是用于跳过脚本路径的团状模式数组。

例如,使用:

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

所有代码node_modules以及自由党项目中的文件夹会被跳过。该skip文件也请申请拨打时显示的地址console.log以及类似的方法:堆栈中第一个未跳过的位置会显示在调试控制台的输出旁边。

Node.js内置的核心模块可以用“神奇名称”来称呼<node_internals>团状模式呈现。以下示例跳过所有内部模块:

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

具体的“跳过”规则如下:

  • 如果你进入跳过的文件,你不会停在那里——你会停在下一个不在跳过文件中的执行行。
  • 如果你设置了在抛出异常时破坏的选项,那么除非异常从跳过的文件中冒出来,否则你不会破坏异常。
  • 如果你在跳过的文件中设置断点,你会在该断点停止,你可以逐步穿过它直到跳出断点,然后正常跳过行为恢复。
  • 跳过文件内部控制台消息的位置将显示为调用堆栈中第一个未被跳过的位置。

跳过的源代码以“调暗”风格显示在调用堆栈视图中:

在调用栈视图中,跳过的源会被调暗

鼠标悬停在调暗条目上就能解释栈框变暗的原因。

调用栈中的一个上下文菜单项,Toggle 跳过此文件可以让你在运行时轻松跳过文件,而无需将其添加到启动配置中。该选项仅在当前调试会话中持续存在。你也可以用它来停止跳过被skip文件在启动配置里选这个选项。

注:遗产协议调试器支持负的球状模式,但它们必须遵循正向模式:正向模式会增加跳过文件的集合,而负模式则从该文件集中减去。

以下内容中 (遗产仅协议)示例中,除“数学”模块外,其他模块均被跳过:

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

注:遗产协议调试器必须模拟skip文件因为V8调试协议本身不支持此功能。这可能导致步进性能变慢。

调试 WebAssembly

JavaScript调试器可以调试编译成WebAssembly的代码,前提是包含DWARF调试信息。许多工具链支持发送以下信息:

  • C/C++ 与 Emscripten:编译为-g标记以发送调试信息。
  • Zig:DWARF 信息会在“调试”构建模式下自动输出。
  • Rust:Rust 会输出 DWARF 调试信息。然而,wasm-pack在构建过程中尚未保留该接口。所以,与其逃跑WASM-pack 构建,使用常见的WASM-BindGen/WASM-Pack库的用户应使用两个命令手动构建:
    1. 货物安装 WASM-Bindgen-CLI一次是安装必要的命令行工具。
    2. 货物建造——目标WASM32-未知-未知为了建立你的图书馆。
    3. WASM-bindgen --keep-debug --out-dir pkg ./target/wasm32-unknown-unknown/debug/<library-name>.wasm <extra-arguments>生成WebAssembly绑定,替换<图书馆名>用你Cargo.toml的名称和配置<额外争论>必要时。

代码完成后,你需要安装WebAssembly DWARF调试扩展。该扩展作为独立扩展发布,以保持VS Code核心的“简化”。安装后,重启所有正在进行的调试会话,本地代码应映射到调试器中!你应该会看到源代码显示在加载源代码视图中,断点应该能正常工作。

在下图中,调试器在C++源代码中的断点被停止,该断点生成了一个曼德博分形。调用栈可见,包含从 JavaScript 代码到 WebAssembly 再到 映射后的 C++ 代码的帧。你还可以在C++代码中看到变量,以及对int32关联内存的编辑高度变数。

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

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

  • 变量视图中的变量无法直接编辑。不过,你可以选择变量旁边的“查看二进制数据”作来编辑其关联内存。
  • 调试控制台观察视图中的基本表达式由 lldb-evaval 提供。这与普通的JavaScript表达式不同。
  • 未映射到源代码的位置将以反汇编的 WebAssembly 文本格式显示。对于WebAssembly,命令“禁用源映射步进”会使调试器只在反汇编代码中步进。

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

支持的类节点运行时

当前的VS CodeJavaScript调试器支持Node版本8.x或更高版本、最新Chrome版本以及Edge最新版本(通过MSEDGE发射类型)。

下一步

如果你还没读Node.js部分,可以看看:

  • Node.js - 端到端节点场景及示例应用

想看VS Code调试基础的教程,可以看看这个视频:

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

  • 任务——与Gulp、Grunt和Jake一起执行任务。显示错误与警告

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

  • 调试器扩展——从模拟样本开始创建VS Code调试扩展的步骤

常见问题

是的,如果你已经为项目内的文件夹创建了符号链接,比如NPM链接你可以通过告诉Node.js运行时保持对称链接路径来调试符号链接的源。用node.exe--保留符号链接 在你的发射配置中切换runtimeArgs属性。runtimeArgs,一组字符串,被传递给调试会话运行时的可执行文件,该程序默认为node.exe。

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

如果你的主脚本在一个共鸣路径中,那么你还需要添加“--保留-符号链接-主”选项。该选项仅在节点10+中提供。

我该如何调试ECMAScript模块?

如果你用ESM还是通过--实验模块为了Node.js使用ECMAScript模块,您可以将这些选项传递给runtimeArgs属性launch.json:

我该如何设置NODE_OPTIONS?

调试器使用 特殊NODE_OPTIONSenvironment 变量 用于设置与你的应用程序进行调试,并且覆盖它会阻止调试正常工作。与其覆盖它,不如直接添加内容。例如,一个.bashrc文件可能包含这样的内容:

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