VSCode Vue 调试
如何在 VSCode 中设置断点,直接调试 Vue 代码?
以下所有运行环境的 node 版本:v16.15.1
1 vue-cli 4 创建的 vue 项目
以下操作和设置,在由 vue-cli 4 创建的 vue2/js 项目下进行,应该也适用于 vue-cli 4 下创建的其它类型项目,没有进一步尝试。
vue-cli 4 对应的 webpack 版本为 4.x
一些前置条件
VSCode 已经内置 JaveScript Debugger,不需要再安装 Debugger for Chome。
microsoft/vscode-js-debug: The VS Code JavaScript debugger

VSCode 需要配置 launch.json
Debugging in Visual Studio Code
在项目中,添加 launch.json 文件,可以选择多种调试器。

如果已经创建,则还可以添加配置。

这里是配置属性的含义说明:
Debugging in Visual Studio Code
launch.json 配置
需要添加 sourceMapPathOverrides
vscode-js-debug/OPTIONS.md at ab0b7d74c66a837c2ab6918f7bb81a8fc3c61663 · microsoft/vscode-js-debug
{
  // 使用 IntelliSense 了解相关属性。 
  // 悬停以查看现有属性的描述。
  // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Launch Chrome",
      "request": "launch",
      "type": "chrome",
      "url": "http://localhost:8080",
      "webRoot": "${workspaceFolder}/src",
      "sourceMapPathOverrides": {
        "webpack:///src/*": "${webRoot}/*"
      }
    }
  ]
}
注意 webRoot 要设置正确,需要和 sourceMapPathOverrides 中的路径对应。
vue.config.js 配置
webpack 相关 | Vue CLI
添加 vue.config.js配置文件,添加 webpack 配置。
module.exports = {
    configureWebpack: {
        devtool: 'source-map'
    }
}
调试运行
在终端中使用 yarn serve 运行,然后在 vscode 启动调试,就可以命中断点了。

2 vue-cli 5 创建的 vue 项目
vue-cli 5 对应的 webpack 版本为 5.x,在 vue-cli 5 下创建的 vue 项目,不能通过类似上面比较简单的设置,就开启在 VSCode 中的断点调试支持。
以下的配置在 vue2/js,vue3/js,vue3/ts 下测试 OK,但操作有点复杂,不像是支持一个调试功能需要的设置,不然门槛有点太高了。如果知道其它简单的方式,求告知。
方案来源:Vue + TypeScript & Debuggers - ckh|Consulting
准备工作
添加 source-map 包,被安装的版本为 "^0.7.4"。
yarn add source-map -D
launch.json 配置
{
  // 使用 IntelliSense 了解相关属性。
  // 悬停以查看现有属性的描述。
  // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Launch Chrome",
      "request": "launch",
      "type": "chrome",
      "url": "http://localhost:8080",
      "webRoot": "${workspaceFolder}",
      "sourceMapPathOverrides": {
        "webpack://<name-from-package.json>/./src/*": "${webRoot}/src/*"
      },
    }
  ]
}
注意,上面的 <name-from-package.json> 需要替换为项目名称
vue.config.js
const { defineConfig } = require("@vue/cli-service");
const fs = require('fs');
const { SourceMapConsumer, SourceMapGenerator } = require('source-map');
module.exports = defineConfig({
  transpileDependencies: true,
  configureWebpack:  {
    devtool : "source-map",
    plugins: [{
      apply(compiler) {
        compiler.hooks.thisCompilation.tap('Initializing Compilation', (compilation) => {
          compilation.hooks.finishModules.tapPromise('All Modules Built', async (modules) => {
            for (const module of modules) {
              if (shouldSkipModule(module)) continue;
              const pathWithoutQuery = module.resource.replace(/\?.*$/, '');
              const sourceFile = fs.readFileSync(pathWithoutQuery).toString('utf-8');
              const sourceMap = extractSourceMap(module);
              sourceMap.sources = [pathWithoutQuery];
              sourceMap.sourcesContent = [sourceFile];
              sourceMap.mappings = await shiftMappings(sourceMap, sourceFile, pathWithoutQuery);
            }
          });
        });
      }
    }]
  }
});
function shouldSkipModule(module) {
  const { resource = '' } = module;
  if (!resource) return true;
  if (/node_modules/.test(resource)) return true;
  if (!/\.vue/.test(resource)) return true;
  if (!/type=script/.test(resource)) return true;
  if (!/lang=ts/.test(resource)) return true;
  if (isMissingSourceMap(module)) return true;
  return false;
}
function isMissingSourceMap(module) {
  return !extractSourceMap(module);
}
function extractSourceMap(module) {
  if (!module['_source']) return null;
  return module['_source']['_sourceMap'] ||
    module['_source']['_sourceMapAsObject'] ||
    null;
}
async function shiftMappings(sourceMap, sourceFile, sourcePath) {
  const indexOfScriptTag = getIndexOfScriptTag(sourceFile);
  const shiftedSourceMap = await SourceMapConsumer.with(sourceMap, null, async (consumer) => {
    const generator = new SourceMapGenerator();
    consumer.eachMapping((mapping) => {
      const {
        generatedColumn,
        generatedLine,
        originalColumn,
        originalLine
      } = mapping;
      let name = mapping.name;
      let source = sourcePath;
      var original = null
      if (originalLine === null || originalColumn === null) {
        name = null;
        source = null;
      }
      else {
        original = {
          column: originalColumn,
          line: originalLine + indexOfScriptTag,
        };
      }
      generator.addMapping({
        generated: {
          column: generatedColumn,
          line: generatedLine,
        },
        original,
        source,
        name
      });
    });
    return generator.toJSON();
  });
  return shiftedSourceMap.mappings;
}
function getIndexOfScriptTag(sourceFile) {
  const lines = sourceFile.match(/.+/g);
  let indexOfScriptTag = 0;
  for (const line of lines) {
    ++indexOfScriptTag;
    if (/<script/.test(line)) break;
  }
  return indexOfScriptTag;
}
以上代码还是来自 Vue + TypeScript & Debuggers - ckh|Consulting,源码见:vue-typescript-debugger/vue.config.js at master · fearnycompknowhow/vue-typescript-debugger
需要注意的是,以上源码,做了一点小修复:添加了 var original = null 的定义,不然编译可能报错。
运行调试
通过 yarn serve 运行项目,在 VSCode 中启动调试,就可以命中断点了。
注意,launch.json 的配置的启动 url,需要随配置修改。
3 vite 创建的 vue 项目
这里的 vite 版本是 2.9.13
npm info vite version
如果使用 vite 创建 vue 项目,不管是 vue2、vue3,还是 js/ts,让 VSCode 支持调试,都非常简单。
yarn create vite
launch.json
只要添加 "webRoot": "${workspaceFolder}/src" 就可以了
{
    // 使用 IntelliSense 了解相关属性。 
    // 悬停以查看现有属性的描述。
    // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch Chrome",
            "request": "launch",
            "type": "chrome",
            "url": "http://localhost:3000",
            "webRoot": "${workspaceFolder}/src"
        }
    ]
}
运行调试
然后直接运行,yarn dev,接着就可以在 VSCode 中启动调试了。

参考文章
在VS Code 中调试Vue.js - SegmentFault 思否
Vue + TypeScript & Debuggers - ckh|Consulting

                
            
        
浙公网安备 33010602011771号