Chrome 是一款浏览器,对前端工程师来说也是一款调试利器,下面的几个功能是我在工作中最常用到的几个,下面逐个介绍。
断点
添加断点可以直接在代码中硬编码,增增加一行debugger 表达式即可,代码执行到此处会断到此处:
在 VSCode 中,黄色下划线表示警告。一般不会使用此方式,因为此方式跟
console.log 并没有明显的优势,甚至还不如前者简单,因为你用完之后还得删了,不然代码是不可用的。
还有一种方式是直接在 devtools 中的 source tab 中找到源码,一般是通过 console.log 输出后,点击控制台右侧的文件名,可以在 Sources tab 中看到源码,点击左下角格式化之后,在代码左侧行号出点击标记断点,即可调试,如下图:
断点后,图中红色部分的按钮,从左向右依次的含义:
继续执行:点击后,断点将直接执行到下一个断点处。setp over:如果当前断点所在位置不是函数,则跟step一样,执行到下一行;如果是函数,则会跳过该函数继续执行到下一行。setp into:如果没有异步代码,则跟setp一样,执行到下一行;如果有异步代码,但它会进入到异步代码的内部第一行。step out:点击后,跳出当前函数。setp:执行下一行同步代码,跟step into不一样, 它会跳过异步代码的执行;如果当前断点在函数处的话,会进入到函数调用内部第一行。暂时停用/激活断点:首次点击后会临时禁止断点功能,就像没有打断点一样代码不会停止执行,下方的Breakpoints中的断点会整体置灰:
将断点停在报错处点击高亮后启用,代码将会自动停止到任何 throw error 的地方,无论是否是被 catch 住,也无论是 http 错误还是什么错误。注意必须把下面的Pause on caught exceptions勾选才行,不勾选等于无效:
此功能最好是在代码执行一遍完成后,页面载入完成后,开始交互的时候打开,否则可能一进入页面就会报错,包括 React 中的合法报错等,导致无法正常加载页面。
直接放一张官方断点的图:
上图中上述的按钮下面有一系列的 toggle
‣ 三角号可以点击,依次为:
Watch可以监测断点处的任何可访问到的上下文变量以供显示,如果变量不存在或者无法访问,如访问a.b.c的时候,a 不存在,那么会显示不可用。当断点断的时候,该位置输入的变量会自动显示,而不用鼠标悬浮上去(像上面官方图一样)查看变量,很方便。Breakpoints表示已经有的断点。checkbox 打勾的是可用的断点,未打勾的是暂时忽略的断点(可以临时打勾或者取消掉)。
当前执行到的断点,背景是黄色的。
Threads表示当前调用的文件线程,当期页面 JavaScript 线程表示为Main中。此部分一般用不到,只是用来调试Web Worker比较有用,也可以用来在当前页面调试 Chrome 浏览器插件。Scope显示当前断点处的可访问到的变量值。因为 JavaScript 的闭包和调用栈的特性,会显示很多闭包中的变量:
Call Stack即函数的调用栈,最顶层的是最近的调用,可以通过点击不同的函数在其之间来回跳。需要注意的是,跳转的时候不会真的再次执行到那个位置,只是方便你查看那个位置的闭包变量。
UI 断点
有些情况下,你不知道或者无从定位一个 UI 问题为什么会这么变化。比如,你的同事写了一个 hover 到按钮上之后,按钮颜色变化的代码。你需要为这个逻辑添加新的逻辑,但是你并不知道他的代码逻辑写在哪个文件(他没有交接工作就休假了,可恶!)。
你发现 hover 到按钮上的时候,按钮会增加个 class 类名,于是你可以使用 dom 断点进行调试,在 Elements tab 中,你需要检查的那个元素上右键:
UI 断点可以将代码停到你指定的 UI 事件所执行的代码发生之前的那一刻,UI 事件包括:
- 子树修改:如果子树有任何修改,如增加、属性变更等,会将代码断到该逻辑即将执行的地方。
- 属性修改:如果当前右键的元素有任何修改,会将代码断到该逻辑即将执行的地方。
- 节点移除:如果当前右键的元素移除,会将代码断到该逻辑即将执行的地方。
举个例子,飞书文档中,如果 block 聚焦,则会在节点上添加一个 focus 类名:
此时就可以使用
attribute modifications 进行断点:
当然,默认情况下线上代码是压缩后的,点击左下角的
{} 就会格式化:
格式化之后,Chrome 会新建一个 tab,在文件后面加上
:formatted :
需要注意的是,如果你右键的元素在变更的时候是父节点变更,如父节点整体移除,则 UI 断点不会执行。
Overwrite
Charles 有类似的功能叫 Map js(没记错的话),ProxyMan 的类似功能叫 Map Local,都是一个意思。
有时候,因为上线/测试链路比较长(尤其是编辑器这种基础工具组件,需要发包),想快速验证一个 case 的时候就会比较麻烦,因此可以使用 Chrome 的 Overwrite 功能。
此功能类似于 Charles 的 Map js 功能,即可以将本地文件作为页面的请求进行响应,你需要先在 Sources 中启用该功能,当然,如果没有指定本地的文件存储的位置,需要先让你指定位置才行:
此时 Chrome 会提醒你需要本地该路径的完全访问权限,同意即可:
然后转到
Network tab,选择一个资源,如 css/js,我这里选择的是 js:
注意,如果没有在
Sources 中启用 Overwrite 的话,这里是不会显示 Save for overrides 的。
之后就可以各种修改该文件,然后刷新页面查看修改后的效果了。
需要注意的是,如果 js 文件请求后有时间戳,则 Overwrite 不会生效,因为 Chrome 是使用严格的路径匹配来 map 文件的。
Snippet
准确说,这个不算是「调试方法」,但是平常有个代码验证的片段,我也会存到这个里面,相当于一个 Sublime(可以对输入过的变量进行自动补全),挺好用的:
Filesystem
该功能跟上面几个在同一个位置,用来实时同步浏览器中的修改到本地文件系统。该功能适合一个简单的 HTML Web 服务,如 Express 这种服务端返回 js/css/html 等的本地调试时候用。
但是该功能官方明确说了,不适合 React App。因为现在基本项目都是 React、Vue 等的现代框架构建的,因此此功能用的较少,这里仅放个官方截图: