• 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 支持调试,都非常简单。

    开始 | Vite 官方中文文档

    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

    原文链接:https://www.cnblogs.com/jasongrass/p/16438571.html

  • 相关阅读:
    Vue 数组响应
    Vue 事件监听
    Vue 分支循环
    Vue 计算属性与方法
    Vue 属性与样式
    Vue mustache语法&常用指令
    vue 基本介绍
    linux(centos7) 安装nginx
    python 创建虚拟环境(一个独立的环境)
    Python标准库学习--->1、内置函数(1-10个)
  • 原文地址:https://www.cnblogs.com/jasongrass/p/16438571.html
Copyright © 2020-2023  润新知