Chrome 常用调试方法及其他

✍🏼 写于 2022年08月07日    💡 更新于 2022年08月12日
❗️ 注意:离本文创建时间已经过去了 天,请注意时效性
🖥  说明:Chrome 的调试功能很强大,这里介绍一下我工作中最常用的几个功能。
📚  本文同步发布在 Craft:https://www.craft.do/s/20CjMjTupEMXFc

Chrome 是一款浏览器,对前端工程师来说也是一款调试利器,下面的几个功能是我在工作中最常用到的几个,下面逐个介绍。

断点

这个应该是用的最多的基础功能,但是我面试过的很多外包同学并不知道如何使用 Chrome 的断点调试,或者听说过,但是不知道怎么用,下面简单介绍一下基本操作。

添加断点可以直接在代码中硬编码,增增加一行debugger 表达式即可,代码执行到此处会断到此处:

Image

在 VSCode 中,黄色下划线表示警告。一般不会使用此方式,因为此方式跟 console.log 并没有明显的优势,甚至还不如前者简单,因为你用完之后还得删了,不然代码是不可用的。

还有一种方式是直接在 devtools 中的 source tab 中找到源码,一般是通过 console.log 输出后,点击控制台右侧的文件名,可以在 Sources tab 中看到源码,点击左下角格式化之后,在代码左侧行号出点击标记断点,即可调试,如下图:

Image

断点后,图中红色部分的按钮,从左向右依次的含义:

  • 继续执行 :点击后,断点将直接执行到下一个断点处。

  • setp over :如果当前断点所在位置不是函数,则跟 step 一样,执行到下一行;如果是函数,则会跳过该函数继续执行到下一行。

  • setp into :如果没有异步代码,则跟 setp 一样,执行到下一行;如果有异步代码,但它会进入到异步代码的内部第一行。

  • step out :点击后,跳出当前函数。

  • setp :执行下一行同步代码,跟 step into 不一样, 它会跳过异步代码的执行;如果当前断点在函数处的话,会进入到函数调用内部第一行。

  • 暂时停用/激活断点 :首次点击后会临时禁止断点功能,就像没有打断点一样代码不会停止执行,下方的 Breakpoints 中的断点会整体置灰:

Image

Image

  • 将断点停在报错处 点击高亮后启用,代码将会自动停止到任何 throw error 的地方,无论是否是被 catch 住,也无论是 http 错误还是什么错误。注意必须把下面的Pause on caught exceptions 勾选才行,不勾选等于无效:

Image

此功能最好是在代码执行一遍完成后,页面载入完成后,开始交互的时候打开,否则可能一进入页面就会报错,包括 React 中的合法报错等,导致无法正常加载页面。

直接放一张官方断点的图:

官方图👆🏻

上图中上述的按钮下面有一系列的 toggle 三角号可以点击,依次为:

  • Watch 可以监测断点处的任何可访问到的上下文变量以供显示,如果变量不存在或者无法访问,如访问 a.b.c 的时候,a 不存在,那么会显示不可用。当断点断的时候,该位置输入的变量会自动显示,而不用鼠标悬浮上去(像上面官方图一样)查看变量,很方便。

  • Breakpoints 表示已经有的断点。checkbox 打勾的是可用的断点,未打勾的是暂时忽略的断点(可以临时打勾或者取消掉)。

Image

当前执行到的断点,背景是黄色的。

  • Threads 表示当前调用的文件线程,当期页面 JavaScript 线程表示为 Main 中。此部分一般用不到,只是用来调试Web Worker 比较有用,也可以用来在当前页面调试 Chrome 浏览器插件。

  • Scope 显示当前断点处的可访问到的变量值。因为 JavaScript 的闭包和调用栈的特性,会显示很多闭包中的变量:

Image

  • Call Stack 即函数的调用栈,最顶层的是最近的调用,可以通过点击不同的函数在其之间来回跳。需要注意的是,跳转的时候不会真的再次执行到那个位置,只是方便你查看那个位置的闭包变量。

UI 断点

有些情况下,你不知道或者无从定位一个 UI 问题为什么会这么变化。比如,你的同事写了一个 hover 到按钮上之后,按钮颜色变化的代码。你需要为这个逻辑添加新的逻辑,但是你并不知道他的代码逻辑写在哪个文件(他没有交接工作就休假了,可恶!)。

你发现 hover 到按钮上的时候,按钮会增加个 class 类名,于是你可以使用 dom 断点进行调试,在 Elements tab 中,你需要检查的那个元素上右键:

Image

UI 断点可以将代码停到你指定的 UI 事件所执行的代码发生之前的那一刻,UI 事件包括:

  • 子树修改:如果子树有任何修改,如增加、属性变更等,会将代码断到该逻辑即将执行的地方。

  • 属性修改:如果当前右键的元素有任何修改,会将代码断到该逻辑即将执行的地方。

  • 节点移除:如果当前右键的元素移除,会将代码断到该逻辑即将执行的地方。

举个例子,飞书文档中,如果 block 聚焦,则会在节点上添加一个 focus 类名:

Image

Image

此时就可以使用 attribute modifications 进行断点:

Image

当然,默认情况下线上代码是压缩后的,点击左下角的 {} 就会格式化:

Image

格式化之后,Chrome 会新建一个 tab,在文件后面加上 :formatted :

Image

需要注意的是,如果你右键的元素在变更的时候是父节点变更,如父节点整体移除,则 UI 断点不会执行。

Overwrite

Charles 有类似的功能叫 Map js(没记错的话),ProxyMan 的类似功能叫 Map Local,都是一个意思。

有时候,因为上线/测试链路比较长(尤其是编辑器这种基础工具组件,需要发包),想快速验证一个 case 的时候就会比较麻烦,因此可以使用 Chrome 的 Overwrite 功能。

此功能类似于 Charles 的 Map js 功能,即可以将本地文件作为页面的请求进行响应,你需要先在 Sources 中启用该功能,当然,如果没有执定本地的文件存储的位置,需要先让你指定位置才行:

Image

此时 Chrome 会提醒你需要本地该路径的完全访问权限,同意即可:

Image

选择一个本地文件夹后,(这里我选用的是 ~/Developer/Overwrite 文件夹)就可以启用 Overwrite 功能:

Image

然后转到 Network tab,选择一个资源,如 css/js,我这里选择的是 js:

Image

注意,如果没有在 Sources 中启用 Overwrite 的话,这里是不会显示 Save for overrides 的。

之后就可以各种修改该文件,然后刷新页面查看修改后的效果了。

需要注意的是,如果 js 文件请求后有时间戳,则 Overwrite 不会生效,因为 Chrome 是使用严格的路径匹配来 map 文件的。

Snippet

准确说,这个不算是「调试方法」,但是平常有个代码验证的片段,我也会存到这个里面,相当于一个 Sublime(可以对输入过的变量进行自动补全),挺好用的:

Image

Filesystem

该功能跟上面几个在同一个位置,用来实时同步浏览器中的修改到本地文件系统。该功能适合一个简单的 HTML Web 服务,如 Express 这种服务端返回 js/css/html 等的本地调试时候用。

但是该功能官方明确说了,不适合 React App。因为现在基本项目都是 React、Vue 等的现代框架构建的,因此此功能用的较少,这里仅放个官方截图:

Image

其他

MacVim

上面的 Overwrite 来的 js 一般都是压缩后的线上代码,有些可能会比较大,所以我一般会用 Vim 打开后格式化一下。Vim 配置起来太费劲,而 MacVim 提供了开箱即用的体验,稍加改造即可为己更好的所用。为什么用 MacVim 是因为它性能非常强,格式化大到几十 Mb 的文件都是几秒钟的事情。我一般都会配置一个 js-beautify 进行格式化,虽然叫 js-beautify,但是它可以格式化 js、css、html。

使用 js-beautify 需要先安装 vim-plug ,它是一款 vim 插件管理器:https://github.com/junegunn/vim-plug,使用步骤见:https://github.com/junegunn/vim-plug/wiki/tutorial

注:安装需要魔法。

js-beautify 使用这个:https://github.com/beautify-web/js-beautify

这是我的 vim 配置,我使用 [] 快捷键作为调用 js-beautify 的方式,这样就不用每次都输入命令了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
set number
set relativenumber
set smartindent
set autoindent
set hlsearch
set display=lastline
set scrolloff=3
set laststatus=2
set showmatch
set ruler
set guifont=Monaco:h12
syntax on
autocmd FileType *.js setlocal equalprg=js-beautify\ --stdin
nmap [] :%!js-beautify<CR>
colorscheme evening
call plug#begin(has('nvim') ? stdpath('data') . '/plugged' : '~/.vim/plugged')
Plug 'jelera/vim-javascript-syntax'
call plug#end()
if !has('gui')
    set term=$TERM
endif

VSCode

VSCode 也有断点调试功能(感谢 Chrome 内核),但是只能调试 Node 应用(可以配合浏览器插件调试 Web 应用,但是没必要,因为已经有 Chrome 了),基本使用方法跟 Chrome 类似,这里就不介绍了,放个图:

Image

- EOF -