VSCode debugger 调试指南

在以前的文章 深入前端调试原理,我们主要从原理的角度来看了如何调试。本篇文章则是从实践角度出发,看看如何在 vscode 中配置和使用各种调试功能。

本文涉及到代码均在仓库 vscode-debugger-dojo,全面的 VSCode Debugger 调试示例项目,涵盖了各种常见场景的调试配置。

VSCode Debugger 原理

在 VSCode 的项目中 .vscode/launch.json 中加入如下的配置即可调试:

SCode 并不是 JS 语言的专属编辑器,它可以用于多种语言的开发,自然不能对某一种语言的调试协议进行深度适配,所以它提供了 Debugger 适配层和适配器协议,不同的语言可以通过提供 Debugger 插件的形式,增加 VSCode 对不同语言的调试能力:

如此,VSCode Debugger 就能以唯一的 Debugger 前端调试各个不同的语言,插件市场中也提供了诸多不同语言的调试插件:

因此需要使用 type 字段来配置对应的 Debugger 适配器,在前端场景主要是 node 或者 chrome,分别对应 node 和浏览器环境。

调试模式

调试模式通过 request 的方式指定如何启动和链接调试器。

Attach 模式

调试的前后端之间是通过 websocket 进行通信的,所以确保前后端能正确的连接是调试成功的关键。

除了在需要调试的网页中直接打开 Devtools 的方式外,我们使用第三方前端工具进行调试时,都需要知道所需要调试的网页的后端 ws 地址才行。因此我们需要让 Chrome 以指定调试端口的形式跑起来,使用 --remote-debugging-port 参数指定调试端口:

ini 复制代码
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222

Chrome 运行参数非常多,可以通过 该文档 进行查看。

在 Chrome 运行起来后,随意的打开几个网页,然后访问 localhost:9222/json/list 网址,此时就能得到所有运行的网页后端 ws 地址:

在百度网页中同时打开了 Devtools, 可以看到连 Devtools 的调试信息都一起打印出来了,因为 Devtools 本质上也是一个网页程序,所以甚至可以做到对 Devtools Debugger 进行 Debug 这样的套娃操作。

有了 ws 信息,我们就可以使用其他 Debugger 进行连接了,比如使用下面的 VSCode Debug 配置:

Node.js 程序在运行时则是通过 --inspect 或者 --inspect-brk 参数开启调试模式:

Node.js 调试协议经过了漫长的迭代,最终也是以 CDP 协议进行调试,因此 Node.js 程序可以直接使用 Devtools 进行调试,在 Chrome 中访问 chrome://inspect/#devices 就可以看到调试目标了:

如果当前的 Node 项目没有被发现,可能是检测端口不是默认的 9229 ,可以通过 Configure 进行配置。

VSCode Debugger 同样能够连接上 Node.js 项目并进行调试,

Launch 模式

前面讲到的都是首先通过调试模式启动一个项目,然后再手动进行前端 ws 连接,最后再调试的模式。相对较繁琐,VSCode Debugger 提供了 launch 模式,它相当于是将上面的流程自动化了,以调试模式将 Chrome 或者 Node.js 程序运行起来,然后 Debugger 自动 attach 到调试端口,直接调试。

常见配置

launch.json 核心字段

每个调试配置都需要以下基础字段:

字段 说明 可选值 / 示例
type 调试器类型 nodechromelldb
request 调试模式 launch(启动)、attach(附加)
name 配置名称 任意描述性名称

常用配置项

Node.js 调试配置项

bash 复制代码
{
  "type": "node",
  "request": "launch",
  "name": "Node.js Debug",
  "program": "${workspaceFolder}/index.js",
  "args": ["--port", "3000"],
  "cwd": "${workspaceFolder}",
  "env": {
    "NODE_ENV": "development"
  },
  "skipFiles": ["<node_internals>/**", "**/node_modules/**"],
  "console": "integratedTerminal",
  "runtimeExecutable": "node",
  "runtimeArgs": ["-r", "ts-node/register"]
}

配置说明:

  • program:程序入口文件
  • args:传递给程序的命令行参数
  • cwd:工作目录
  • env:环境变量
  • skipFiles:调试时跳过的文件(如 node 内部代码)
  • console:终端类型(integratedTerminalinternalConsoleexternalTerminal
  • runtimeExecutable:运行时可执行文件(如 nodenpmpnpm
  • runtimeArgs:传递给运行时的参数

Chrome 调试配置项

bash 复制代码
{
  "type": "chrome",
  "request": "launch",
  "name": "Chrome Debug",
  "url": "http://localhost:3000",
  "webRoot": "${workspaceFolder}",
  "userDataDir": "${workspaceFolder}/.chrome-data",
  "runtimeArgs": ["--auto-open-devtools-for-tabs"],
  "sourceMaps": true,
  "sourceMapPathOverrides": {
    "webpack:///./~/*": "${webRoot}/node_modules/*",
    "webpack:///./*": "${webRoot}/*"
  }
}

配置说明:

  • url:要打开的网页地址
  • webRoot:Web 根目录,用于源码映射,本质上就是对 sourcemapPathOverrides 的快捷配置方式
  • userDataDir:Chrome 用户数据目录,保存登录状态和扩展
  • runtimeArgs:传递给 Chrome 的启动参数
  • sourceMaps:是否启用 Source Map
  • sourceMapPathOverrides:源码路径映射覆盖规则

Compound 配置

使用 compounds 可以同时启动多个调试会话:

json 复制代码
{
  "compounds": [
    {
      "name": "Full Stack Debug",
      "configurations": ["Server", "Client"],
      "stopAll": true
    }
  ]
}

VSCode 变量

在配置中可以使用以下变量:

变量 说明
${workspaceFolder} 工作区根目录
${file} 当前打开的文件完整路径
${relativeFile} 相对于工作区的文件路径
${fileBasename} 文件名(含扩展名)
${fileBasenameNoExtension} 文件名(不含扩展名)
${fileDirname} 文件所在目录
${cwd} 当前工作目录
${env:NAME} 环境变量 NAME 的值

可参考官方文档:Variables reference

输入变量

使用 inputs 可以在启动调试时要求用户输入:

bash 复制代码
{
  "configurations": [
    {
      "name": "Debug with args",
      "args": ["${input:testName}"]
    }
  ],
  "inputs": [
    {
      "id": "testName",
      "type": "promptString",
      "description": "输入测试名称",
      "default": "test_example"
    }
  ]
}

典型场景

Vite + React 项目

在常规的 React 项目中,通常可以通过先启动完 vite dev 项目后,再运行如下配置启动调试:

bash 复制代码
{
  "type": "chrome",
  "request": "launch",
  "name": "Vite React",
  "url": "http://localhost:5173",
  "webRoot": "${workspaceFolder}/packages/vite-react-demo",
  "runtimeArgs": ["--auto-open-devtools-for-tabs"]
}

保存登录状态

但如此一次,每次启动的 chrome 都是一个全新的实例,没有任何的插件或者登录信息。如果我们希望每次启动的 chrome 都是带上 react 插件,并且保留登录信息,可以通过 userDataDir 自定用户信息目录,然后在第一次安装插件后,后续就无需在处理了:

bash 复制代码
{
  "userDataDir": "${workspaceFolder}/packages/vite-react-demo/.chrome-data"
}

任务集成

如果不希望单独运行 vite dev,而是在每次启动调试时,自行运行 vite dev 后再开启调试,可以通过 preLaunchTaskpostDebugTask 可以在调试前后执行任务:

json 复制代码
{
  "type": "chrome",
  "request": "launch",
  "name": "Vite React Debug",
  "url": "http://localhost:5173",
  "preLaunchTask": "vite-react: dev",
  "postDebugTask": "kill-vite-react-dev"
}

需要在 .vscode/tasks.json 中定义对应的任务:

json 复制代码
{
  "version": "2.0.0",
  "tasks": [
    {
      "label": "vite-react: dev",
      "type": "npm",
      "script": "dev",
      "isBackground": true,
      "problemMatcher": {
        "background": {
          "activeOnStart": true,
          "beginsPattern": ".",
          // 说明 task 准备完成
          "endsPattern": "ready in"
        }
      }
    }
  ]
}

Task 配置属于锦上添花,不是调试过程中的必须配置,更多信息可以参考官网 Integrate with External Tools via Tasks

Next.js 全栈调试

Next.js 同时包含客户端和服务端代码,所以我们的调试场景既包含了 node 端,也包含了 chrome 端。可以借助 serverReadyActioncompounds 两种方式同时连接 node ,web 端 debugger 调试器。

serverReadyAction 一个强大的自动化调试配置,它允许你在服务器启动后,自动触发一个额外的任务,比如针对 Chrome 浏览器的调试会话,从而实现 全栈调试

compounds 则是同时启动多个调试,但是不处理调试之间的依赖关系。

serverReadyAction:debugWithChrome

在启动完成 node 后端后,如果 node 控制台检测到输出了 pattern 内容,则开启一个 chrome 调试窗口:

perl 复制代码
{
  "type": "node",
  "request": "launch",
  "name": "Next.js - Full Stack",
  "runtimeExecutable": "pnpm",
  "runtimeArgs": ["next", "dev"],
  "serverReadyAction": {
    "pattern": "Local:\s+(https?://.+)",
    "action": "debugWithChrome",
    "uriFormat": "%s",
    "webRoot": "${workspaceFolder}"
  },
  "cwd": "${workspaceFolder}",
  "console": "integratedTerminal",
  "skipFiles": ["<node_internals>/**"]
}

但是该模式下对 chrome 调试器的配置很有限,比如 userDataDir 都无法配置,适用于在开启后端调试后,同时兼顾简单的前端调试。

serverReadyAction:startDebugging

startDebugging 则更强大,可以在服务器启动后自动启动另一个客户端调试配置,这样客户端的配置就是完整的,可以完成使用各种标准配置

bash 复制代码
{
  "type": "node",
  "request": "launch",
  "name": "Next.js - Server",
  "runtimeExecutable": "pnpm",
  "runtimeArgs": ["next", "dev"],
  "serverReadyAction": {
    "pattern": "Local:\s+(https?://.+)",
    "action": "startDebugging",
    "name": "Next.js - Client"
  },
  "cwd": "${workspaceFolder}",
  "console": "integratedTerminal",
  "skipFiles": ["<node_internals>/**"]
}

配合的客户端配置:

bash 复制代码
{
  "type": "chrome",
  "request": "launch",
  "name": "Next.js - Client",
  "url": "http://localhost:3000",
  "webRoot": "${workspaceFolder}"
}

Compounds

不使用 serverReadyAction 时,通常单独各个端的调试配置,然后通过 compounds 同时启动多个独立的调试会话:

json 复制代码
{
  "compounds": [
    {
      "name": "Next.js - Full Stack",
      "configurations": ["Next.js - Server", "Next.js - Client"],
      "stopAll": true
    }
  ]
}

三种方式对比:

方式 优点 缺点 适用场景
debugWithChrome 配置简单,一键启动 调试会话合并,控制粒度较粗 日常开发
startDebugging 自动化程度高,会话独立 需要两个配置 需要独立控制前后端
Compound 完全手动控制,灵活性高 需要手动管理多个会话 复杂调试场景

serverReadyAction 还有一种 action openExternally,它的作用更为直接,会在 server 启动后,直接打开在 chrome 打开一个页面,但是不连接客户端调试,只是为了方便交互客户端后,调试服务端。

基本上涉及到多端调试的场景都可以用类似的方案,比如 electron, express 前后端 mono repo 项目等等。

Node 项目

TypeScript 项目

在开发 node ts 项目时,除了编译完成后在运行 js 程序,也可以采用 tsx 或者 ts-node 直接运行 ts 程序,它们会在项目运行前自动进行编译操作。

需要在 runtimeArgs 增加 -r 参数来使用,也可以直接将 runtimeExecutable 进行替换。

使用 tsx(推荐,启动快):

perl 复制代码
{
  "type": "node",
  "request": "launch",
  "name": "TypeScript - Current File (tsx)",
  "program": "${file}",
  // 或者
  // "runtimeExecutable": "tsx",
  "runtimeArgs": ["-r", "tsx/cjs"],
  "cwd": "${workspaceFolder}",
  "console": "integratedTerminal",
  "skipFiles": ["<node_internals>/**"]
}

使用 ts-node(完整类型检查):

perl 复制代码
{
  "type": "node",
  "request": "launch",
  "name": "TypeScript - Current File (ts-node)",
  "program": "${file}",
  // 或者
  // "runtimeExecutable": "ts-node",
  "runtimeArgs": ["-r", "ts-node/register"],
  "cwd": "${workspaceFolder}",
  "console": "integratedTerminal",
  "skipFiles": ["<node_internals>/**"],
  "env": {
    "TS_NODE_PROJECT": "${workspaceFolder}/tsconfig.json"
  }
}

Pnpm 管理项目

在 npm/yarn 管理的 Node 项目中,通常可以直接通过 program 指定 node_modules/.bin 下的命令文件:

bash 复制代码
{
  "type": "node",
  "request": "launch",
  "name": "Jest",
  "program": "${workspaceFolder}/node_modules/.bin/jest"
}

但在 pnpm 项目中,这种方式会失败。

问题根源: pnpm 出于性能和磁盘空间考虑,使用了独特的依赖管理方式,将 .bin 目录下的文件转化为 shell 脚本:

当尝试用 node 直接执行这些文件时,会报错:

javascript 复制代码
SyntaxError: Invalid or unexpected token

因为 Node.js 无法直接执行 shell 脚本文件。

方案 1:使用 pnpm 执行 - 将 runtimeExecutable 改为 pnpm,通过 runtimeArgs 传递命令:

bash 复制代码
{
  "type": "node",
  "request": "launch",
  "name": "Jest - pnpm",
  "runtimeExecutable": "pnpm",
  "runtimeArgs": ["jest", "--runInBand"],
  "cwd": "${workspaceFolder}",
  "console": "integratedTerminal",
  "skipFiles": ["<node_internals>/**"]
}

方案 2:直接指向 JS 文件 - 绕过 shell 脚本,直接指向包内的 JavaScript 入口文件:

bash 复制代码
{
  "type": "node",
  "request": "launch",
  "name": "Jest - direct",
  "program": "${workspaceFolder}/node_modules/jest/bin/jest.js",
  "args": ["--runInBand"],
  "cwd": "${workspaceFolder}",
  "console": "integratedTerminal",
  "skipFiles": ["<node_internals>/**"]
}

方案 3:使用 sh 执行 - 让 sh 来执行 shell 脚本:

bash 复制代码
{
  "type": "node",
  "request": "launch",
  "name": "Jest - sh",
  "runtimeExecutable": "sh",
  "program": "${workspaceFolder}/node_modules/.bin/jest",
  "args": ["--runInBand"],
  "cwd": "${workspaceFolder}",
  "console": "integratedTerminal",
  "skipFiles": ["<node_internals>/**"]
}

实际应用示例:

调试 Vitest 当前文件:

bash 复制代码
{
  "type": "node",
  "request": "launch",
  "name": "Vitest - Current File",
  "runtimeExecutable": "pnpm",
  "runtimeArgs": ["vitest", "run", "${relativeFile}"],
  "cwd": "${workspaceFolder}",
  "console": "integratedTerminal",
  "skipFiles": ["<node_internals>/**"]
}

调试 ESLint:

bash 复制代码
{
  "type": "node",
  "request": "launch",
  "name": "ESLint - Current File",
  "runtimeExecutable": "pnpm",
  "runtimeArgs": ["eslint", "${file}", "--fix"],
  "cwd": "${workspaceFolder}",
  "console": "integratedTerminal"
}

使用直接路径调试 TypeScript:

bash 复制代码
{
  "type": "node",
  "request": "launch",
  "name": "TSC - Build",
  "program": "${workspaceFolder}/node_modules/typescript/bin/tsc",
  "args": ["--noEmit"],
  "cwd": "${workspaceFolder}",
  "console": "integratedTerminal"
}

单测

Jest 单元测试

在运行单侧时,通常有两种场景,运行所有单侧,和运行当前单侧文件的单测。

调试当前打开的测试文件:

bash 复制代码
{
  "type": "node",
  "request": "launch",
  "name": "Jest - Current File",
  "program": "${workspaceFolder}/node_modules/jest/bin/jest.js",
  "args": [
    "${relativeFile}",
    "--config=${workspaceFolder}/jest.config.js",
    "--runInBand",
    "--no-coverage"
  ],
  "cwd": "${workspaceFolder}",
  "console": "integratedTerminal",
  "internalConsoleOptions": "neverOpen"
}

关键参数:

  • --runInBand:串行运行测试(调试必需)
  • --no-coverage:禁用覆盖率收集,加快调试速度

调试所有测试:

bash 复制代码
{
  "type": "node",
  "request": "launch",
  "name": "Jest - All Tests",
  "program": "${workspaceFolder}/node_modules/jest/bin/jest.js",
  "args": ["--runInBand", "--config=${workspaceFolder}/jest.config.js"],
  "cwd": "${workspaceFolder}",
  "console": "integratedTerminal"
}

Vitest 单元测试

调试当前测试文件:

bash 复制代码
{
  "type": "node",
  "request": "launch",
  "name": "Vitest - Current File",
  "runtimeExecutable": "pnpm",
  "runtimeArgs": ["vitest", "run", "${file}"],
  "cwd": "${workspaceFolder}",
  "console": "integratedTerminal",
  "skipFiles": ["<node_internals>/**"]
}

监视模式:

bash 复制代码
{
  "type": "node",
  "request": "launch",
  "name": "Vitest - Watch Mode",
  "runtimeExecutable": "pnpm",
  "runtimeArgs": ["vitest"],
  "cwd": "${workspaceFolder}",
  "console": "integratedTerminal",
  "skipFiles": ["<node_internals>/**"]
}

npm script 调试

通常,我们会将实际运行的程序写入到 npm scripts 中,所以也通过通过以下方式直接调试 script 脚本,就不需要在 launch.json 中重定义一套配置了:

方式一:使用 node 类型:

bash 复制代码
{
  "type": "node",
  "request": "launch",
  "name": "npm script - Start",
  "runtimeExecutable": "npm",
  "runtimeArgs": ["run-script", "start"],
  "cwd": "${workspaceFolder}",
  "console": "integratedTerminal",
  "skipFiles": ["<node_internals>/**"]
}

方式二:使用 node-terminal 类型:

bash 复制代码
{
  "type": "node-terminal",
  "name": "npm script - Start (Terminal)",
  "request": "launch",
  "command": "npm start",
  "cwd": "${workspaceFolder}"
}

Puppeteer 自动化调试

有些时候,调试准备调试数据,尤其是表单类的应用,除了在代码中进行处理,也可以借助 puppeteer 自动化前置的流程,直达要调试的阶段。

通过脚本 启动 puppeteer ,并搭配 --remote-debugging-port=9222 开启调试端口,在启动 puppeteer 后,通过 attach 模式连接 chrome 就可以自动化前置内容填写和连接 chrome 调试器两个阶段:

调试 Puppeteer 脚本:

bash 复制代码
{
  "type": "node",
  "request": "launch",
  "name": "Puppeteer - Script",
  "program": "${workspaceFolder}/scripts/auto-fill-form.js",
  "cwd": "${workspaceFolder}",
  "console": "integratedTerminal",
  "skipFiles": ["<node_internals>/**"],
  "env": {
    "HEADLESS": "false"
  }
}

Chrome Attach 配置:

bash 复制代码
{
  "type": "chrome",
  "request": "attach",
  "name": "Puppeteer - Chrome Attach",
  "port": 9222,
  "webRoot": "${workspaceFolder}"
}

同时调试 Puppeteer 脚本和浏览器代码:

json 复制代码
{
  "compounds": [
    {
      "name": "Puppeteer - Full Stack",
      "configurations": ["Puppeteer - Script", "Puppeteer - Chrome Attach"],
      "stopAll": true
    }
  ]
}

puppeteer 脚本可以直接借助 ai 来生成,编写成本也非常低

快捷调试方式

除了使用 launch.json 配置外,VSCode 也提供了很多便捷的开启调试的手段。相对于通过 ui 交互简化了配置过程。

Package.json 调试按钮

VSCode 会在 package.json 的 scripts 上方显示调试按钮,点击即可快速调试脚本。

使用方式:

  1. 打开 package.json 文件
  2. 在 scripts 字段上方会出现 "Debug" 按钮
  3. 点击按钮即可开始调试

Testing 面板

VSCode 提供了统一的测试面板,支持 Jest、Vitest、Mocha 等测试框架。

启用方式:

  1. 安装对应的测试扩展(如 Jest Runner、Vitest)
  2. 打开测试面板(左侧活动栏的烧杯图标)
  3. VSCode 会自动发现项目中的测试

可以非常便捷的在面板完成单侧的运行。

并且在单测文件中,每个单测也有便捷的调试按钮:

参考:VSCode Testing 文档

Auto Attach

Auto Attach 是 VSCode 提供的一个非常方便的功能,可以自动附加调试器到在集成终端中启动的 Node.js 进程,可以在配置中打开:

三种模式:

模式 说明 适用场景
Smart 自动检测常见脚本,如 npm scripts 推荐,日常使用
Always 附加到所有 Node.js 进程 调试所有 Node 程序
Only With Flag 仅附加到使用 --inspect 标志的进程 精确控制

使用示例:

启用 Auto Attach 后,在集成终端中直接运行:

bash 复制代码
node src/index.js
# 或
npm run dev
# 或
pnpm test

调试器会自动附加。

参考:auto-attach

经典问题

为什么断点不生效

最常见的是为什么明明设置了断点,调试器也连接了,但是就是没有停住。此时添加的断点是灰色的:

可以鼠标 hover 断点进行简单诊断:

常见原因:

launch.json 配置关闭了 sourcemap

sourceMaps 默认是 true, 如果改为了 false 就不会加载 sourcemap 了

json 复制代码
{
  "type": "chrome",
  "request": "launch",
  "name": "Vite React - Launch (自定义用户信息)",
  "url": "http://localhost:5173",
  "runtimeArgs": ["--auto-open-devtools-for-tabs"],
  "sourceMaps": false
}

Source Map 配置错误

确保构建工具正确生成了 Source Map:

TypeScript (tsconfig.json):

json 复制代码
{
  "compilerOptions": {
    "sourceMap": true,
    "inlineSourceMap": false,
    "sourceRoot": ""
  }
}

Vite (vite.config.ts):

arduino 复制代码
export default {
  build: {
    sourcemap: true,
  },
};

Webpack (webpack.config.js):

java 复制代码
module.exports = {
  devtool: "source-map", // 或 'eval-source-map' 用于开发
};

源码路径映射错误

即使所有的 sourcemap 配置都正常,也可能会出现问题,常见于 webpack。比如 webpack 生成的 sourcemap 是:

映射出的原始文件以 webpack:// 开头,比如 webpack://webpack-demo/./src/app.ts,而我们打的断点在 ${workspaceFolder}/packages/webpack-demo/src/app.ts。VSCode 不知道两者关系,此时需要 sourceMapPathOverrideswebRoot 修正 Source Map 路径与本地文件路径的映射。

配置说明:

  1. webRoot 的作用 - webRoot 指定 Web 应用的源码根目录,作为 Source Map 路径映射的基准路径。在 sourceMapPathOverrides 中可以通过 ${webRoot} 变量引用这个基准路径。
  2. sourceMapPathOverrides 配置 - 当 Source Map 中的路径与本地文件路径不匹配时,使用 sourceMapPathOverrides 修正路径映射:
kotlin 复制代码
{
  "type": "chrome",
  "request": "launch",
  "name": "Chrome Debug",
  "url": "http://localhost:3000",
  "webRoot": "${workspaceFolder}/packages/webpack-demo",
  // 相当于:
  "sourceMapPathOverrides": {
    "webpack://webpack-demo/./src/*": "${webRoot}/src/*",
    "webpack://webpack-demo/./*": "${webRoot}/*"
  }
}

默认配置:

如果不配置 sourceMapPathOverrides,VSCode 会使用以下默认规则 (适用于 Chrome/浏览器调试):

bash 复制代码
{
  "sourceMapPathOverrides": {
    "webpack:///./~/*": "${webRoot}/node_modules/*",
    "webpack:///./*": "${webRoot}/*",
    "webpack:///*": "*",
    "webpack:///src/*": "${webRoot}/*",
    "meteor://💻app/*": "${webRoot}/*"
  }
}

注意: 对于 Node.js 调试,默认规则中使用 ${workspaceFolder} 替代 ${webRoot}

配置说明:

  • 左侧是 Source Map 中的路径模式
  • 右侧是本地文件系统的实际路径
  • * 是通配符,匹配任意路径片段
  • 映射规则从上到下匹配,使用第一个匹配的规则

常见打包工具的配置示例:

  1. Webpack 项目:
bash 复制代码
{
  "sourceMapPathOverrides": {
    "webpack:///./*": "${webRoot}/*",
    "webpack:///src/*": "${webRoot}/src/*",
    "webpack:///*": "${webRoot}/*"
  }
}
  1. Vite 项目:
javascript 复制代码
Vite 的 Source Map 路径通常已经是正确的,一般不需要额外配置。但如果遇到问题:
perl 复制代码
{
  "sourceMapPathOverrides": {
    "/@fs/*": "/*",
    "/src/*": "${webRoot}/src/*"
  }
}
  1. Monorepo 项目:
bash 复制代码
{
  "webRoot": "${workspaceFolder}/packages/your-app",
  "sourceMapPathOverrides": {
    "webpack:///packages/your-app/*": "${webRoot}/*",
    "webpack:///../your-app/*": "${webRoot}/*"
  }
}

假设:

  • webRoot = "${workspaceFolder}/packages/app"
  • Source Map 路径: webpack://app/./src/index.ts

映射规则:

bash 复制代码
{
  "sourceMapPathOverrides": {
    "webpack://app/./*": "${webRoot}/*"
  }
}

映射过程:

  1. webpack://app/./src/index.ts 匹配规则 webpack://app/./*
  2. * 匹配到 src/index.ts
  3. 替换为 ${webRoot}/src/index.ts
  4. 展开 ${webRoot} 得到最终路径: ${workspaceFolder}/packages/app/src/index.ts

调试器启动慢

原因:

  • 项目文件过多
  • Source Map 文件过大
  • skipFiles 配置不当

优化方法:

  1. 跳过不必要的文件
bash 复制代码
{
  "skipFiles": [
    "<node_internals>/**",
    "**/node_modules/**",
    "${workspaceFolder}/dist/vendor.js"
  ]
}
  1. 限制 Source Map 查找范围
bash 复制代码
{
  "outFiles": ["${workspaceFolder}/dist/**/*.js", "!**/node_modules/**"]
}
  1. 使用更快的 Source Map 类型
python 复制代码
开发环境使用 `eval-source-map`:
arduino 复制代码
// webpack.config.js
devtool: "eval-source-map"; // 比 'source-map' 快但体积大

总结

vscode debugger 是非常强大的,可以极大提升调试效率。并且设置虽多,关键的就是那几个,配置也不麻烦。了解了 vscode debugger 能做哪些事情后,搭配 AI, 更是进一步简化了配置的难度。

欢迎关注笔者的个人公众号,共同学习,共同前进

相关推荐
一颗宁檬不酸2 小时前
页面布局练习
前端·html·页面布局
zhenryx3 小时前
React Native 自定义 ScrollView 滚动条:开箱即用的 IndicatorScrollView(附源码示例)
javascript·react native·react.js·typescript
金木讲编程3 小时前
Claude、Agent与Copilot协作生成Angular应用
前端·ai编程
振华OPPO4 小时前
Vue:“onMounted“ is defined but never used no-unused-vars
前端·javascript·css·vue.js·前端框架
欧雷殿4 小时前
在富阳银湖成立地域化的软件研发团队
前端·程序员·创业
狂炫冰美式5 小时前
前端实时推送 & WebSocket 面试题(2026版)
前端·http·面试
JefferyXZF5 小时前
新手建站零门槛!Vercel+Cloudflare+Namesilo域名购买部署全流程
前端
yinuo5 小时前
微信浏览器缓存机制大揭秘:为什么你总刷不出新页面?
前端
拉不动的猪5 小时前
try...catch 核心与生态协作全解析
前端·javascript·vue.js