我不知道的 VSCode 扩展:调试技巧与最佳实践

517 字 16 min read
前端开发 VSCode 扩展开发 调试 Debug 断点 日志 最佳实践

引言

🐞 在前面的文章中,我们已经学习了 VSCode 扩展开发的方方面面,从基础知识、用户界面、API 到生命周期。现在,我们将聚焦于 VSCode 扩展的调试。调试是软件开发过程中不可或缺的一环。掌握高效的调试技巧,可以帮助我们快速定位和解决扩展中的 Bug,提升开发效率,保证代码质量。本文将系统地介绍 VSCode 扩展的调试技巧和最佳实践,让你在扩展开发过程中如虎添翼,轻松应对各种 Bug,写出高质量的 VSCode 扩展。现在,就让我们一起开启 VSCode 扩展调试的探索之旅!

VSCode 扩展调试基础

🛠️ VSCode 提供了强大的内置调试功能,可以方便地调试 VSCode 扩展。调试 VSCode 扩展主要涉及以下几个方面:

  • 启动调试配置: 配置调试器,指定调试的扩展和启动参数。
  • 设置断点: 在代码中设置断点,让程序在特定位置暂停执行。
  • 单步调试: 逐行执行代码,观察程序执行流程。
  • 查看变量: 在调试过程中查看变量的值,了解程序状态。
  • 调用堆栈: 查看函数调用堆栈,了解程序执行路径。
  • 控制台输出: 查看控制台输出,例如 console.log() 的信息。

启动调试配置

⚙️ 要调试 VSCode 扩展,首先需要配置调试启动配置。VSCode 使用 launch.json 文件来配置调试器。

  1. 打开 "运行和调试" 视图: 点击 VSCode 侧边栏的 "运行和调试" 图标 (或按下 Ctrl+Shift+D / Cmd+Shift+D),打开 "运行和调试" 视图。
  2. 创建 launch.json 文件: 点击 "创建 launch.json 文件" 链接 (如果还没有 launch.json 文件),选择 "Node.js 附加到进程" 环境 (或 "Node.js 附加到进程 (legacy)")。VSCode 会自动在你的项目根目录下创建 .vscode/launch.json 文件,并生成一个默认的调试配置。

默认生成的 launch.json 文件内容可能如下所示:

{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "node",
            "request": "attach",
            "name": "Attach to Process",
            "processId": "${command:PickProcess}"
        }
    ]
}

你需要修改 launch.json 文件,配置一个适合调试 VSCode 扩展的调试配置。一个常用的 VSCode 扩展调试配置如下所示:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "扩展调试", // 调试配置的名称,显示在 "运行和调试" 视图的下拉列表中
            "type": "extensionHost", // 调试类型,固定为 "extensionHost",表示调试 VSCode 扩展
            "request": "launch", // 请求类型,"launch" 表示启动一个新的 VSCode 扩展宿主进程来调试扩展
            "runtimeExecutable": "${execPath}", // VSCode 的可执行文件路径,使用 ${execPath} 变量表示当前 VSCode 的可执行文件路径
            "args": [
                "--extensionDevelopmentPath=${workspaceFolder}" // 扩展开发路径,指向当前工作区根目录,VSCode 会加载该目录下的扩展
            ],
            "stopOnEntry": false, // 是否在程序入口处 (activate 函数) 暂停执行,默认为 false
            "sourceMaps": true, // 是否启用 Source Map,用于调试 TypeScript 代码,默认为 true
            "outFiles": [ // 输出文件路径,用于指定编译后的 JavaScript 文件路径,用于 Source Map 查找源文件
                "${workspaceFolder}/out/**/*.js" // 默认的 TypeScript 编译输出目录为 "out" 目录
            ],
            "preLaunchTask": "npm: watch" // 启动调试前要执行的任务,这里配置为 "npm: watch" 任务,表示在调试前先运行 "npm run watch" 命令编译 TypeScript 代码
        }
    ]
}

配置项说明:

  • name: 调试配置的名称,可以自定义,显示在 "运行和调试" 视图的下拉列表中。
  • type: 调试类型,必须设置为 "extensionHost",表示调试 VSCode 扩展。
  • request: 请求类型,必须设置为 "launch",表示启动一个新的 VSCode 扩展宿主进程来调试扩展。
  • runtimeExecutable: 必须设置为 ${execPath},表示使用当前 VSCode 的可执行文件来启动扩展宿主进程。
  • args: 启动参数,必须包含 --extensionDevelopmentPath=${workspaceFolder},表示指定扩展开发路径为当前工作区根目录。
    • 你还可以添加其他启动参数,例如 --locale=zh-cn 指定 VSCode 语言为中文,--disable-extensions 禁用所有其他扩展等。
  • stopOnEntry: 可选,默认为 false。设置为 true 表示在扩展的入口函数 activate() 处暂停执行,方便你从扩展激活开始调试。
  • sourceMaps: 可选,默认为 true必须设置为 true 来启用 Source Map,才能调试 TypeScript 源代码。
  • outFiles: 可选,用于指定编译后的 JavaScript 文件路径。如果你的 TypeScript 编译输出目录不是默认的 "out" 目录,需要修改 outFiles 配置,确保 VSCode 能够找到编译后的 JavaScript 文件,从而正确加载 Source Map。
  • preLaunchTask: 可选,用于指定启动调试前要执行的任务。通常配置为 "npm: watch""npm: compile" 任务,表示在调试前先编译 TypeScript 代码。你需要确保你的项目中配置了相应的 npm 任务 (例如在 package.json 文件中定义了 watchcompile 脚本)。

设置断点

🛑 断点是调试器在代码执行到特定位置时暂停执行的标记。你可以在 VSCode 编辑器中通过以下方式设置断点:

  1. 鼠标点击: 在编辑器行号的左侧空白区域单击鼠标左键,即可在该行设置断点。断点会显示为一个红色实心圆点。再次单击可以取消断点。
  2. 快捷键: 将光标移动到要设置断点的行,按下 F9 快捷键,即可在该行设置或取消断点。

你可以在代码的任何可执行行设置断点,例如函数调用、变量赋值、循环语句、条件语句等。

启动调试

▶️ 配置好调试启动配置并设置好断点后,就可以启动调试了。

  1. 选择调试配置: 在 "运行和调试" 视图的顶部,确保下拉列表框中选择了你配置的调试配置 (例如 "扩展调试")。
  2. 启动调试: 点击绿色的 "启动调试" 按钮 (或按下 F5 快捷键),即可启动调试。

VSCode 会启动一个新的 扩展开发宿主 窗口,并在该窗口中加载你的扩展进行调试。当程序执行到你设置的断点时,程序会暂停执行,VSCode 会切换到调试视图,显示当前的调试信息。

单步调试、查看变量、调用堆栈

🚶‍♀️ 当程序在断点处暂停执行时,你可以使用 VSCode 提供的调试工具进行单步调试、查看变量、调用堆栈等操作:

  • 单步调试:

    • 单步跳过 (Step Over): F10 快捷键。执行当前行代码,然后跳到下一行。如果当前行是函数调用,则直接执行完整个函数,跳到函数调用之后的下一行。
    • 单步调试 (Step Into): F11 快捷键。执行当前行代码,如果当前行是函数调用,则进入函数内部,跳到函数的第一行代码。
    • 单步跳出 (Step Out): Shift+F11 快捷键。从当前函数跳出,返回到调用当前函数的位置。
    • 继续 (Continue): F5 快捷键。继续执行程序,直到遇到下一个断点或程序结束。
    • 重新启动 (Restart): Ctrl+Shift+F5 / Cmd+Shift+F5 快捷键。重新启动调试会话。
    • 停止 (Stop): Shift+F5 快捷键。停止调试会话。
  • 查看变量: 在调试视图的 "变量" 面板中,可以查看当前作用域内所有变量的值。你可以展开对象和数组,查看其内部属性和元素。你也可以在 "监视" 面板中添加要监视的变量,以便在调试过程中随时观察这些变量的值变化。

  • 调用堆栈: 在调试视图的 "调用堆栈" 面板中,可以查看当前的函数调用堆栈。调用堆栈显示了程序执行到当前位置的函数调用路径。你可以点击堆栈帧,切换到不同的函数调用栈帧,查看该栈帧的局部变量和代码执行位置。

控制台输出

📝 在调试过程中,你仍然可以使用 console.log(), console.warn(), console.error() 等方法在控制台输出信息。扩展开发宿主窗口的 "输出" 面板 (选择 "扩展宿主") 会显示这些控制台输出信息。 你可以在代码中插入 console.log() 语句,输出一些调试信息,例如变量的值、程序执行路径等。

VSCode 扩展调试最佳实践

💡 除了掌握基本的调试技巧外,以下是一些 VSCode 扩展调试的最佳实践,可以帮助你更高效地调试扩展:

  1. 使用 Source Map 调试 TypeScript 代码: 务必启用 Source Map ("sourceMaps": true),并正确配置 "outFiles",以便能够直接调试 TypeScript 源代码,而不是编译后的 JavaScript 代码。这可以大大提高调试效率,因为你可以直接在熟悉的 TypeScript 代码中设置断点、单步调试、查看变量,而无需查看难以理解的 JavaScript 代码。

  2. 配置 preLaunchTask 编译代码: 配置 "preLaunchTask": "npm: watch""npm: compile",确保在每次启动调试前都先编译 TypeScript 代码。使用 "npm: watch" 任务可以在后台自动监听文件变化并重新编译,提高开发效率。

  3. 使用条件断点: 条件断点 是指只有当满足特定条件时才会触发的断点。你可以在设置断点时,右键点击断点,选择 "编辑断点",然后输入条件表达式。例如,你可以设置条件 i === 10,只有当循环变量 i 的值等于 10 时,断点才会触发。条件断点可以帮助你更精确地定位问题,减少不必要的断点触发。

  4. 使用日志输出: 合理使用 console.log(), console.warn(), console.error() 等日志输出语句,在代码中输出一些关键信息,例如变量的值、函数调用参数、程序执行路径等。即使不启动调试器,你也可以通过查看扩展开发宿主窗口的 "输出" 面板来了解程序的运行状态。在生产环境中,应该移除或禁用不必要的日志输出,避免影响性能和泄露敏感信息。

  5. 利用 VSCode 扩展的测试框架: VSCode 官方提供了 vscode-test 框架,用于编写和运行 VSCode 扩展的集成测试和单元测试。编写测试用例可以帮助你更全面地测试扩展的功能,尽早发现和修复 Bug。 你可以使用 VSCode 的 "测试" 视图运行测试用例,并进行调试。

  6. 调试激活和卸载过程: 你可以activate()deactivate() 函数中设置断点,调试扩展的激活和卸载过程,了解扩展的初始化和清理逻辑是否正确执行。

  7. 调试 Webview: 调试 Webview 的 JavaScript 代码可以使用 Chrome DevTools。 在 Webview 中打开开发者工具 (通常是右键菜单 "检查" 或 "Inspect"),即可使用 Chrome DevTools 调试 Webview 的 JavaScript 代码,查看控制台输出、Elements 面板、Sources 面板、Network 面板等。

  8. 使用扩展开发宿主窗口: 所有扩展相关的操作和输出 (例如 console.log()、错误提示、扩展激活信息等) 都会显示在扩展开发宿主窗口中。 在调试扩展时,要密切关注扩展开发宿主窗口,查看是否有错误提示或异常信息。

总结

🎉 恭喜你,完成了 VSCode 扩展调试技巧与最佳实践的学习!本文系统地介绍了 VSCode 扩展调试的基础知识、调试流程和最佳实践。掌握这些调试技巧,可以帮助你更高效地开发和调试 VSCode 扩展,提升开发效率,保证代码质量。记住,调试是软件开发过程中不可或缺的一环,熟练掌握调试技巧是成为优秀扩展开发者的必备技能。在接下来的扩展开发实践中,不断运用和巩固这些调试技巧,相信你一定能够开发出高质量、稳定可靠的 VSCode 扩展!