简介 本文会以一个全新的 Vue.js 项目作为模板进行配置,你可以跟随教程一步步操作,也可以按照教程将配置添加到已有的项目中。
仓库地址:https://github.com/mrlmx/debug-vuejs-project-with-vscode
创建项目通过 vue 提供的 create-vue [1] 脚手架,创建一个 vue3 项目。
npm init vue@latest
注意:通过上述命令,创建的是基于 vite 的项目,而不是基于 webpack 的项目。
然后在 VS Code 中打开创建后的项目:
code ./debug-vuejs-project-with-vscode
code
是 VS Code 自带的命令,如果你运行时提示没有此命令,可以看官方文档 launching-from-the-command-line [2] 设置一下。debug-vuejs-project-with-vscode
是我的项目名称。 生成 sourcemap 文件 Vite如果是通过 create-vue [3] 创建的项目,则修改 vite.config.ts 配置文件,在开发环境生成 sourcemap 文件。
export default defineConfig({ build : { sourcemap : true , }, // other configs... });
更多配置,请参考:https://v/config/build-options.html#build-sourcemap
Vue Cli如果是通过 vue-cli [4] 创建的项目,则修改 vue.config.js 配置文件,在开发环境生成 sourcemap 文件。
module .exports = { configureWebpack : { devtool : 'source-map' } // other configs... };
更多配置,请参考:https://cli./guide/webpack.html
Webpack如果是自己搭建的项目,则修改自己定义的 webpack 配置文件,在开发环境生成 sourcemap 文件。
module .exports = { devtool : 'source-map' , // other configs... };
更多配置,请参考:https://webpack./configuration/devtool/#devtool
配置文件 launch.json通过如下步骤,创建 launch.json 配置文件(如果你的项目中已经存在该文件,则可跳过此步骤)。
选择左侧菜单中的 Debug icon,打开调试菜单。 点击 create a launch.json file,创建一个新的配置文件。 选择 Web App(Edge),当然,你也可以选择 Web App(Chrome)。 生成的 launch.json 文件大致长这样(不同版本的 VS Code 可能略有不同):
{ // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 'version' : '0.2.0' , 'configurations' : [ { 'type' : 'pwa-msedge' , 'request' : 'launch' , 'name' : 'Launch Edge against localhost' , 'url' : 'http://localhost:8080' , 'webRoot' : '${workspaceFolder}' } ] }
将生成的 launch.json 文件内容,替换为下方配置:
{ 'version' : '0.2.0' , 'configurations' : [ { // 使用 Edge 浏览器调试 'type' : 'msedge' , // 使用 Chrome 浏览器调试 // 'type': 'chrome', 'request' : 'launch' , 'name' : 'vuejs: msedge' , // 项目的访问地址(需要改成你项目开发环境对应的地址和端口号) 'url' : 'http://localhost:5173' , 'webRoot' : '${workspaceFolder}' , 'pathMapping' : { '/_karma_webpack_' : '${workspaceFolder}' }, 'sourceMapPathOverrides' : { 'webpack:/*' : '${webRoot}/*' , '/./*' : '${webRoot}/*' , '/src/*' : '${webRoot}/*' , '/*' : '*' , '/./~/*' : '${webRoot}/node_modules/*' }, // 设置进入 debug 环境之前需要执行的任务。 // 此名称对应项目中 .vscode 目录下 tasks.json 文件中的 label 属性) 'preLaunchTask' : 'vuejs: start' } ] }
上面的配置中,有以下几点需要注意:
msedge
的意思是使用 Edge 浏览器进行调试。chrome
的意思是使用 Chrome 浏览器进行调试。需要改为你项目的开发环境地址,如果一致则无需修改。 preLaunchTask
:设置进入 debug 环境之前需要执行的任务。此名称对应项目中 .vscode 目录下 tasks.json 文件中的 label 属性。 更多信息:
关于 launch.json 文件的更多配置,请参考: https://code./docs/editor/debugging#_launchjson-attributes tasks.json在项目的 .vscode 目录创建 tasks.json 文件,然后将下方内容粘贴进去:
{ 'version' : '2.0.0' , 'tasks' : [ { 'label' : 'vuejs: start' , 'type' : 'npm' , // 需要执行的命令(对应于 package.json 中的 scripts 命令) 'script' : 'dev' , 'isBackground' : true } ] }
上面的配置在执行时,运行的命令是:npm run dev
,如果你的项目是其他的启动命令,那么修改为对应的 script 名称即可。
注意:type
的其他可选值是 shell
或者 process
,可不要傻乎乎地改成 yarn
。
type
:任务的类型。对于自定义任务,可以设置为 shell
或 process
。
如果设置为 shell
,则该命令将被解释为 shell 命令(例如:bash、cmd 或 PowerShell)。 如果设置为 process
,则该命令将被解释为要执行的进程。 更多信息:
关于 tasks.json 文件的更多配置,请参考: https://code./docs/editor/tasks#_custom-tasks https://code./docs/editor/tasks-appendix 关于 VS Code tasks 功能,更多信息,请参考: https://code./docs/editor/tasks 打断点咱们将 src/views/AboutView.vue 文件的内容稍微改一下,然后打两个断点。
<script lang='ts' setup>import { reactive, ref } from 'vue' ;const other = reactive([ { name : 'lmx' , age : 18 }, { name : 'foo' , age : 20 }, { name : 'bar' , age : 12 }, ]);const count = ref(0 );const handlePlus = () => { console .log('plus before' , count.value); count.value++; console .log('plus after' , count.value); };const handleMinus = () => { console .log('minus before' , count.value); count.value--; console .log('minus after' , count.value); }; </script> <template> <div class='about'> <h1>This is an about page</ h1> <div > <p > {{ count }}</p > <button @click ='handlePlus' > plus</button > <button @click ='handleMinus' > minus</button > <hr style ='margin: 20px 0' /> <p v-for ='item of other' :key ='item.name' > {{ item.name }}: {{ item.age }} </p > </div > </div> </ template>
在第 13 行和 第 19 行,分别打了 2 个断点(在对应行号左边,点击鼠标左键即可打断点):
注意事项需要注意的是:一定要在启动 Debug 前打好断点,否则你将无法匹配到断点。
启动之后,在源文件中添加新的断点是无效的,运行中的编译文件无法匹配到新的断点,除非修改源文件的代码触发编译,这样新生成的编译文件才会映射到新断点。
我猜测的原因是:因为 *.vue
这种 SFC 格式的文件,需要将script
,template
,style
这 3 个模块拆分编译,实际运行的是编译后的 js 文件,而且每次文件修改或者重启项目之后,都会编译出新的文件。
如果不提前打断点,那么源文件和编译后的文件将不会关联上。
弹窗提示另外,我发现:不管是否提前打了断点,在启动时都会提示:
The task 'xxx' cannot be tracked. Make sure to have a problem matcher defined。
我搜了一下,暂时没有找到特别完美的解决方案,这里提供两种蹩脚的方法:
方案一:
如果你不在意这个提示的话,可以每次都点击一下「Debug Anyway」按钮,或者勾选一下「Remember my choice for this task」,以后每次运行的时候就不会提示了,所谓眼不见心不烦。
方案二:
把 launch.json 文件中的 preLaunchTask
属性去掉,Debug 之前自己手动启动项目,反正配置 preLaunchTask
的目的就是自动帮你把项目启动起来,所谓自己动手丰衣足食。
启动 Debug经过上述配置之后,就可以通过 Debug 模式启动项目了,咱们来分别介绍一下「快捷键」和「手动启动」这 2 种启动方式。
快捷键:F5如果你的项目只有 1 个 Debug 配置的话,可以直接通过 F5
快捷键启动 Debug 模式,非常的简单方便,推荐日常使用。
手动启动如果你的项目有多个 Debug 配置,launch.json 文件的 configurations
数组有多个配置对象。
这个时候 F5
快捷键启动的就是第一个配置,如果你想要启动其他 Debug 配置,就需要通过手动选择了。
可以看到,点击「下拉菜单」之后,展示了 2 个配置选项:vuejs: msedge
和 vuejs: chrome
。
示例中 launch.json 配置文件的内容是这样的:
{ 'version' : '0.2.0' , 'configurations' : [ { 'type' : 'msedge' , 'request' : 'launch' , 'name' : 'vuejs: msedge' , 'url' : 'http://localhost:5173' , 'webRoot' : '${workspaceFolder}' , 'pathMapping' : { '/_karma_webpack_' : '${workspaceFolder}' }, 'sourceMapPathOverrides' : { 'webpack:/*' : '${webRoot}/*' , '/./*' : '${webRoot}/*' , '/src/*' : '${webRoot}/*' , '/*' : '*' , '/./~/*' : '${webRoot}/node_modules/*' }, 'preLaunchTask' : 'vuejs: start' }, { 'type' : 'chrome' , 'request' : 'launch' , 'name' : 'vuejs: chrome' , 'url' : 'http://localhost:5173' , 'webRoot' : '${workspaceFolder}' , 'pathMapping' : { '/_karma_webpack_' : '${workspaceFolder}' }, 'sourceMapPathOverrides' : { 'webpack:/*' : '${webRoot}/*' , '/./*' : '${webRoot}/*' , '/src/*' : '${webRoot}/*' , '/*' : '*' , '/./~/*' : '${webRoot}/node_modules/*' }, 'preLaunchTask' : 'vuejs: start' } ] }
看到这里,你应该已经把 debug 的环境配置好了,现在可以开始愉快地调试了。
一些问题在我写这篇文章的过程中,也发现了几个让我头痛的问题,这里顺带提一下。
在开始说这些问题之前,咱们先看一下这张图:
标注 2:是运行时命中断点后,VS Code 自动打开的编译后的文件。 它的名字也有可能是:AboutView.vue?t=1661699383436
。 有一个t
参数,是一个毫秒时间戳,应该是避免缓存的。 1. 必须先打断点我们可以看到,在运行过程中,其实断点命中是编译后的文件。
前面我们提到,在运行 Debug 模式之后再去源文件中添加新断点,正常情况下是无法匹配的。
那如果我在调试过程中,想要添加新断点该怎么办呢?
方法 1: 直接在「编译后的文件」中打新断点。
此方法的弊端是:它是个一次性的断点。
因为新断点是针对这个编译文件的,如果源文件改动后,会重新编译出新的文件,那么这个断点将会失效,后续将不会被匹配到。
方法 2: 直接在「源文件」中打新断点。
此方法的弊端是:需要手动触发编译。
前面也提到过,在源文件中添加新断点之后,运行中的编译文件是无法感知到的,所以必须让源文件触发重新编译,生成新的编译文件,这样源文件的所有断点就会同步映射到新的编译文件中了。
我每次触发重新编译的方式是,随便在某个地方添加一行 console.log('')
,然后每次直接修改打印的内容即可。
2. 断点位置不一致源文件和编译后的文件断点的行号一致,但是对应的行号却是不同的代码,和我们预期的断点位置不一致:
对比之后可以看出,@vue/compiler-sfc [5] 自动将 <script setup> [6] 语法糖转换为了 Composition API [7] 风格代码,并且添加了一些辅助代码。
这就导致单纯地根据行号映射断点位置会有些问题,出现了无法预知的错位情况。
我目前的解决方案是,手动在对应的位置加上 debugger
,确保能够一定命中在我想要的位置上。
然后在命中断点后的编译文件中,加上其他想要的新断点。
3. 改动后会编译出新文件前面已经提到过,在每次修改完源文件后,都会编译出新的文件。这就导致之前在编译文件中的断点全部失效。
一顿调试之后,VS Code 中会有大量的无效断点标记,虽说不影响使用,但是看起来有点头大。
我暂时没有什么好的解决方案,所以只能在每次调试结束之后,点击「Remove All Breakpoints」按钮,移除所有断点。
以上就是我遇到的一些问题,如果你有好的解决方案,可以在评论区告知一下,比心 ❤️。
本文首发于:https://github.com/mrlmx/blogs/issues/3
参考https:///guide/quick-start.html https://github.com/Microsoft/VSCode-recipes/tree/master/vuejs-cli 相关链接 [1] create-vue: https://github.com/vuejs/create-vue
[2] launching-from-the-command-line: https://code./docs/setup/mac#_launching-from-the-command-line
[3] create-vue: https://github.com/vuejs/create-vue
[4] vue-cli: https://github.com/vuejs/vue-cli
[5] @vue/compiler-sfc: https://github.com/vuejs/core/tree/main/packages/compiler-sfc
[6] <script setup>: https:///api/sfc-script-setup.html
[7] Composition API: https:///guide/extras/composition-api-faq.html