【前端】vue+vscode断点调试详解

前言

  • 非开箱即用,仅做好奇心知足、复杂项目中自定义断点配置、下个项目中不求人不百度当即断点调试
  • 涉及面较宽,须要必定经验,且各处均不会太深刻(我也菜)
  • 若是你处处搜索但始终解决不了: vscode没法链接上页面、提示未验证断点(灰空心圆)、断点漂移乱飞到其余行、断点实际中断时所在位置不对、单步跳过执行时去到奇怪的位置,那么这里可能解决问题

js如何断点

如图↑,直接sources面板中打断点。
若在第6行的空行打断点,看到一个动画显示断点从第六行溜到第七行。vscode的debugger扩展实质就是与这个通讯,并反馈结果到本身的ui上。所以若是你看到vscode中用鼠标打的断点与显示不一致,那么实际上是浏览器就是这样作的,只是vscode少了过渡动画,并非vscode的bug,是设定。

SourceMap

阮一峰老师的讲解:JavaScript Source Map 详解
简单来讲,SourceMap可以让压缩/翻译过的最终版的各类文件与原来未压缩过的文件对应起来。那么断点逻辑容易理解:
1.给浏览器提供未压缩的源码和SourceMap文件
2.浏览器跑最终版本的js代码时,经过SourceMap找到对应源码的位置,若是该对应源码处被用户打上了断点标记,那么中断
javascript

同时:
1.仅在你F12打开开发者工具后,浏览器才会去加载最终版代码指示的SourceMap文件(所以基本不影响普通用户加载速度),再根据SourceMap文件指示去加载源码。以下图的文件↓ php

2.线上环境中,能把SourceMap文件也放上去,但不可能把源码也放到服务器。即SourceMap指向源文件位置为 /a.js时,浏览器会加载 协议://域名/a.js,显然线上没有此文件。但咱们能够经过浏览器Sources->Filesystem添加文件夹映射,即映射到本地项目的源码中进行断点调试。固然浏览器窗口会给出相应的ui反馈↓
3.关于这个具体的映射规则,就是把Filesystem里面添加的若干个文件夹视做网站根目录,浏览器自动根据目录结构和文件名寻找对应的文件。但这并不意味你能够随意对应,好比新建一个相似的目录结构并放入空内容的App.vue文件,浏览器并不会将它和源文件关联起来。另外视乎SourceMap的质量(如webpack中有多种生成方式,详略程度不同),可能存在部分映射信息缺少、模块合并后各处代码指向同一个源码位置等等,致使如文章前言提到的各类奇怪表现。
4.若是这里服务器中和本地Filesystem中有一样的源码文件,那么浏览器以本地Filesystem的为准。即忽略从服务器中获取的源码文件,而使用本地Filesystem的文件做SourceMap映射的源文件

vue中配置SourceMap

其实是设置webpack配置中的devtool:'source-map'选项。这里具体位置出入较大,你多是@vue/cli初始化的项目、使用webpack的vue模板构建的项目、项目负责人自行从新组织过的项目等,这里就请自行了解到哪配置webpack了。html

注意:这个devtool:'source-map'能够说是必须的,其余生成SourceMap的方式都不太适合断点而适合分析,不然因为上述缘由出现各类奇怪表现。vue

webpack提供的本地服务器

在最完整的SourceMap设置下你应该能看到这个结构(a.js是我额外加进去的,不用管)↓ java

1.先说下这个 webpack://,这个就是webpack自定义的网络应用层协议,跟 http://https://同样道理。
2.在这个自定义应用层协议中,能够省略域名(相似于ftp)即 webpack:///路径。另外 .真的就是一个文件夹 ,不表明当前目录(http协议中 https://juejin.im/timelinehttps://juejin.im/./timeline一回事)
3.如图, webpack:///src中通常是咱们的原始vue文件, webpack:///./src是部分处理事后的vue和png等资源
4.webpack本地服务器把编译后资源直接放在内存中,你看不到有编译后的本地文件。所以你可能须要先build一下看看咱们的最终打包出来的 app.js和他的 app.js.map有些什么↓
(1) app.js文件中最后一行会是 //# sourceMappingURL=app.js.map,当咱们打开开发者工具,浏览器就会去加载这个map文件。
(2) app.js.map里面应该有这样几行:

"version":3,
  "sources":[
    "webpack:///src/app.js",
    "webpack:///./src/app.js",
    ...
  ]
复制代码

也就是这个SourceMap可以把编译后的代码映射到sources中指示的若干个js源文件的对应位置。
(3)浏览器能够看做一个强大的IDE,此时咱们能够在开发者工具的source面板找到这些文件,并打上断点进行调试node

vscode中调试

实质上vscode调试,就是经过调试扩展链接浏览器以获取调试信息,同时经过本身的ui和交互让咱们感受不到在使用上述浏览器功能。所以若是你发现vscode中调试很奇怪,那么按前面步骤去看看浏览器中能不能正常断点调试,若是浏览器中表现也是这么奇怪,那么无论你vscode怎么配置基本都是徒劳的。理清思路后,进入核心主题(须要安装Debugger for Chrome 这个扩展)webpack

chrome须要的准备功夫

本身命令行启动或者快捷方式,追加启动参数--remote-debugging-port=9222,这个是让chrome打开9222调试端口,咱们的vscode扩展会经过这个端口获取浏览器提供的调试信息。下面vscode会以attach方式链接,所以请先启动浏览器,本地跑你的vue项目,并打开目标页面。ios

Normally, if Chrome is already running when you start debugging with a launch config, then the new instance won't start in remote debugging mode.git

注意,若是你已常常规启动chrome,那么再启动一个chrome通常状况下他不会以远程调试模式启动。所以attach方式请关掉全部chrome实例,而且从新以远程调试模式启动一次(如上面参数,能够直接访问http://localhost:9222看看有没有回应)github

强制配置的参数

  • type - the type of debugger to use for this launch configuration. Every installed debug extension introduces a type: node for the built-in Node debugger, for example, or php and go for the PHP and Go extensions.(大意是说每一个调试扩展都向vscode注册了一个type,vscode根据你设置的type的值去通知不一样扩展进行工做)
  • request - the request type of this launch configuration. Currently, launch and attach are supported.(目前只有两个容许值。在咱们这个状况下,launch表示启动浏览器打开目标页面并attach;attach即直接链接到当前浏览器的目标页面)
  • name - the reader-friendly name to appear in the Debug launch configuration drop-down.(这个配置的名字。实际就是用来切换多种不一样配置的调试)

来源:Debugging

经常使用的可选参数

可选参数并不统一,需查看各个扩展说明。一些绝大部分扩展都支持的参数官网有说明,不重复了。下面是attach方式中这个扩展经常使用的参数:

  • url: On a 'launch' config, it will launch Chrome at this URL.(目标url。若是是launch模式,会直接启动浏览器打开这个页面。而后attach这个页面,即至关于在这个页面启动开发者工具)
  • urlFilter: On an 'attach' config, or a 'launch' config with no 'url' set, search for a page with this url and attach to it. It can also contain wildcards, for example, "localhost:*/app" will match either "http://localhost:123/app" or "http://localhost:456/app", but not "stackoverflow.com".(上面那个url只能精确匹配,这个则容许使用通配符,看它的例子)
  • sourceMaps: By default, the adapter will use sourcemaps and your original sources whenever possible. You can disable this by setting sourceMaps to false.(默认为true。可看成上面提到的把目录加入Filesystem)
  • webRoot: 设置${webRoot}变量。${webRoot}是下面两个参数的默认设置用到的变量,从而使得该参数具备意义
  • pathMapping: This property takes a mapping of URL paths to local paths, to give you more flexibility in how URLs are resolved to local files. "webRoot": "${workspaceFolder}" is just shorthand for a pathMapping like { "/": "${workspaceFolder}" }(实际上做用基本同下面,区别主要是人类“语义”上的区别和默认的设置不一样。常规文件映射用这个,map文件映射用下面那个,但没有严格区分)
  • sourceMapPathOverrides: 下面会详细说。可简单理解为如何设置当前目录到Filesystem进行映射

来源:vscode-chrome-debug

变量

  • ${workspaceFolder} - the path of the folder opened in VS Code
  • ${workspaceFolderBasename} - the name of the folder opened in VS Code without any slashes (/)
  • ${file} - the current opened file
  • ${relativeFile} - the current opened file relative to workspaceFolder
  • ${fileBasename} - the current opened file's basename
  • ${fileBasenameNoExtension} - the current opened file's basename with no file extension
  • ${fileDirname} - the current opened file's dirname
  • ${fileExtname} - the current opened file's extension
  • ${cwd} - the task runner's current working directory on startup
  • ${lineNumber} - the current selected line number in the active file
  • ${selectedText} - the current selected text in the active file
  • ${execPath} - the path to the running VS Code executable

来源:Variables Reference 这个点进去看他举例就能理解了,不翻译了。

sourceMapPathOverrides

设置如何映射。下面是它的默认设置

// Note: These are the mappings that are included by default out of the box, with examples of how they could be resolved in different scenarios. These are not mappings that would make sense together in one project.
// webRoot = /Users/me/project
"sourceMapPathOverrides": {
    "webpack:///./~/*": "${webRoot}/node_modules/*",       // Example: "webpack:///./~/querystring/index.js" -> "/Users/me/project/node_modules/querystring/index.js"
    "webpack:///./*":   "${webRoot}/*",                    // Example: "webpack:///./src/app.js" -> "/Users/me/project/src/app.js",
    "webpack:///*":     "*",                               // Example: "webpack:///project/app.ts" -> "/project/app.ts"
    "webpack:///src/*": "${webRoot}/*",                    // Example: "webpack:///src/app.js" -> "/Users/me/project/app.js"
    "meteor://💻app/*": "${webRoot}/*"                    // Example: "meteor://💻app/main.ts" -> "/Users/me/project/main.ts"
}
复制代码

其中的${webRoot}是咱们自定义值的一个变量。你须要作的,就是保证webpack:///下的各类文件能被正确映射到咱们的开发目录文件。实际就是设置Filesystem(这个某些状况下可右键自定义如何映射到网络资源,不展开了)
注意:sourceMapPathOverrides一旦被自定义设置,那么原来的默认设置无效(就是被从新赋值的意思);存在多个匹配时,后面出现匹配的覆盖前面存在的匹配。

总结

搞了一大堆,其实就是这么几个意思:
1.chrome远程调试模式启动,先确保你知道是哪一个端口可被vscode链接、确保你能在F12里面断点不会有奇奇怪怪的现象
2.vscode建立调试,在launch.json中,点击右下角的添加配置,更改端口port为上面你启动的端口
3.设置url或者urlFilter参数(attach要求你已经打开了这个url对应的页面。launch方式就是多了自动帮你打开这个页面,没多大区别)
4.设置webRoot参数,由于默认的sourceMapPathOverrides中用到了${webRoot} 这个变量
5.等一会,attach上目标页面后,vscode底部栏会变色,能够了。热更新后有问题请刷新页面
6.理解为重,最多见错误是webRoot与sourceMapPathOverrides胡乱设置没有对应上。通常而言,只要你的vue项目是工做目录下有个src文件夹,里面有main.js、App.vue这样结构的话,那么最小化的配置只要6个参数:

{
    "type": "chrome",
    "request": "attach",
    "name": "hello world",
    "port": 9222,
    "webRoot": "${workspaceFolder}/src",
    "url": "http://localhost:8080"
}
复制代码
相关文章
相关标签/搜索