线上页面白屏,用户截图发过来只有一句「我这打不开」。你打开自己的 Chrome,一切正常。这种时候最缺的不是聪明,是一套能把问题「按住」的调试手法:知道去哪个面板看、看哪一列数字、什么时候该上真机、什么时候该在 Node 侧打断点。
这篇是我把日常用到的调试手段整理了一遍的结果,从 Chrome DevTools 的三大面板讲到断点体系,再讲移动端 H5、App 里的 WebView、以及 Node 服务端。每个工具都配了截图,你可以对着图找按钮,不用凭记忆猜位置。
在本篇文章中,我们将从浅入深,和大家一起学习以下知识:
- Chrome DevTools 十个面板各管什么,先建立一张地图
- Console 面板除了
console.log还能做什么 - Network 面板的六个区域,以及一次请求时间线上每一段的含义
- Sources 面板的断点体系:行断点、DOM 断点、XHR 断点、事件断点、异常断点
- 用 Filesystem、Overrides、Snippets 把调试改动留下来
- 移动端 H5 没有控制台时,怎么用 vConsole 兜底
- WebView 是什么,为什么它必须单独调
- Android 用
chrome://inspect连真机,iOS 用 Safari 网页检查器连真机 - Node.js 的
--inspect调试原理,以及 VSCode 里怎么配launch.json - 这些面板在新版 Chrome 里都挪到了哪
# 一、先建一张 DevTools 的地图
Chrome 开发者工具里的面板不少,性能相关的有网络面板、Performance 面板、内存面板,页面调试相关的有 Elements 面板、Sources 面板、Console 面板。很多人用了几年也只在 Console 和 Elements 之间来回切,剩下的面板完全没打开过。
打开方式是在浏览器窗口右上方选择 Chrome 菜单,然后选择「更多工具 → 开发者工具」。快捷键在 Mac 上是 Cmd + Option + I,Windows 上是 F12 或者 Ctrl + Shift + I。
下面这张图是打开后的样子,先看顶部那一排标签,那就是面板列表。

你应该能在顶部数出十来个标签。窗口窄的时候部分标签会被折叠进右边的 » 里,找不到某个面板先去那里翻一翻。
这十个面板分别是:
- Elements
- Console
- Sources
- NetWork
- Performance
- Memory
- Application
- Security
- Audits
- Layers
光看名字还是抽象,下面这张表把每个面板负责的事写出来了,扫一眼就知道遇到什么问题该去哪。

看完这张表你大概能记住一条主线:DOM 和样式的问题去 Elements,脚本执行的问题去 Sources,请求的问题去 Network,卡顿和内存的问题去 Performance 和 Memory。这条主线足够覆盖八成日常场景。
这里补一句版本差异。上面这份面板清单是 2020 年那会儿的样子,Audits 面板后来改名叫 Lighthouse 了,另外新版还多出了 Recorder、Application 下的更多子项等等。不同 Chrome 版本入口位置有差异,你在自己浏览器里数出来的面板数量和这张图对不上是正常的,按功能去找就行。
接下来重点看三个面板:Network、Console、Sources。
# 二、Console 面板不只是 console.log
先说结论,Console 面板真正值钱的地方是它能让你在任意时刻拿到页面的运行时上下文,而不是只能打日志。不过日志确实是最常用的,先把日志的几个等级过一遍。
console.log("打印字符串");//在控制台打印自定义字符串
console.error("我是个错误");//在控制台打印自定义错误信息
console.info("我是个信息");//在控制台打印自定义信息
console.warn("我是个警告");//在控制台打印自定义警告信息
console.debug("我是个调试");//在控制台打印自定义调试信息
这五个方法的区别不只是颜色。Console 面板顶部有个日志等级过滤器(Default levels),能单独勾掉 Verbose、Info、Warning、Error。第三方 SDK 疯狂刷屏的时候,把等级过滤一下比翻页快得多。console.debug 默认属于 Verbose 等级,很多人发现「debug 打不出来」,就是因为这一级默认没勾上。
# 2.1 格式化输出
除此以外,console 还支持自定义样式和类似 C 语言 printf 形式的占位符。这套东西用在给日志分组、给关键日志加高亮上很省事。
console.log("%s年",2016);//%s表示字符串
console.log("%d年%d月",2016,11);//%d表示整数
console.log("%f",3.1415926);//%f小数
console.log("%o",console);//%o表示对象
console.log("%c自定义样式","font-size:30px;color:#00f");
console.log("%c我是%c自定义样式","font-size:20px;color:green","font-size:10px;color:red");
%c 这个我自己用得最多。项目里如果有一类日志你希望一眼扫到,比如埋点上报或者路由切换,给它统一加个背景色,在几百条日志里也能一眼捞出来。要注意 %c 的样式作用范围是从它出现的位置到下一个 %c 为止,所以上面第二行才会出现两段不同样式的文字。
顺着上面聊,%o 打对象和直接 console.log(obj) 有个细微差别:直接打印会给你一个可展开的交互式对象,而且展开时读的是展开那一刻的值,不是打印那一刻的。所以调试对象被后续代码改过的场景,稳妥的做法是 console.log(JSON.parse(JSON.stringify(obj))) 打个快照,或者直接上断点。这个我踩过,排查了一下午发现是日志骗了我。
# 三、Network 面板与一次请求的完整生命周期
网络面板由控制器、过滤器、抓图信息、时间线、详细列表和下载信息概要这 6 个区域构成。先对着下面这张图把六块区域的位置认清楚,后面讲每一块的时候你才知道在说哪。

图里从上往下的分层很清楚。如果你打开面板发现下半部分是空的,多半是没在录制状态下刷新页面,先刷新一次再看。
# 3.1 控制器:四个最该记住的开关
控制器在最上面那一排,功能不少,但真正天天用的就四个。看下面这张图里被标出来的位置。

按图从左往右看,这几个按钮分别是:
- 红色圆点的按钮,表示「开始 / 暂停抓包」,这个功能很常见,很容易理解
- 「全局搜索」按钮,这个功能就非常重要了,可以在所有下载资源中搜索相关内容,还可以快速定位到某几个你想要的文件上
- Disable cache,即「禁止从 Cache 中加载资源」的功能,它在调试 Web 应用的时候非常有用,因为开启了 Cache 会影响到网络性能测试的结果
- Online 按钮,是「模拟 2G/3G」功能,它可以限制带宽,模拟弱网情况下页面的展现情况,然后你就可以根据实际展示情况来动态调整策略,以便让 Web 应用更加适用于这些弱网
这里有个坑要注意,Disable cache 只在 DevTools 打开的时候生效。你关掉 DevTools 再刷新,缓存又回来了。所以「我明明勾了禁用缓存怎么还是老代码」这种情况,先确认面板是不是开着的。
新版 Chrome 里这块的名字变了。Online 那个下拉现在统一叫「节流 / Throttling」,预设档位的名称也随版本调整过,还多了自定义网络配置的入口。功能是同一个,找不到就在控制器那一排横着扫,看哪个下拉里有 No throttling 字样。
# 3.2 过滤器、抓图信息、时间线
网络面板中的过滤器,主要就是起过滤功能。因为有时候一个页面有太多内容在详细列表区域中展示了,而你可能只想查看 JavaScript 文件或者 CSS 文件,这时候就可以通过过滤器模块来筛选你想要的文件类型。
过滤器输入框其实还支持一些关键字语法,比如按域名、按状态码、按大小筛。真正救命的场景是接口特别多的页面,直接输接口路径的一段就能定位到。
抓图信息区域,可以用来分析用户等待页面加载时间内所看到的内容,分析用户实际的体验情况。比如,如果页面加载 1 秒多之后屏幕截图还是白屏状态,这时候就需要分析是网络还是代码的问题了。勾选面板上的「Capture screenshots」即可启用屏幕截图。
那怎么判断到底是网络问题还是代码问题?看截图那一排的时间戳,对照下面详细列表里资源到达的时刻。如果关键 JS 早就下载完了,屏幕还是白的,那问题在渲染或者脚本执行,不在网络。
时间线,主要用来展示 HTTP、HTTPS、WebSocket 加载的状态和时间的一个关系,用于直观感受页面的加载过程。如果是多条竖线堆叠在一起,那说明这些资源被同时被加载。至于具体到每个文件的加载信息,还需要用到下面要讲的详细列表。
# 3.3 下载信息概要里的两个事件
下载信息概要在面板最底部那一条,你要重点关注下 DOMContentLoaded 和 Load 两个事件,以及这两个事件的完成时间。
DOMContentLoaded,这个事件发生后,说明页面已经构建好DOM了,也就是构建DOM所需要的 HTML 文件、JavaScript文件、CSS文件都已经下载完成了Load,说明浏览器已经加载了所有的资源(图像、样式表等)
通过下载信息概要面板,你可以查看触发这两个事件所花费的时间。这两个数字是最粗粒度的体检指标:DOMContentLoaded 长说明关键路径上的资源被阻塞了,Load 长而 DOMContentLoaded 正常,那多半是图片、字体这些非关键资源拖的。关于关键渲染路径怎么优化,我之前单独写过一篇 渲染路径优化,这里就不展开了。
# 3.4 详细列表:一次请求的所有细节
详细列表这个区域是最重要的,它详细记录了每个资源从发起请求到完成请求这中间所有过程的状态,以及最终请求完成的数据信息。通过该列表,你就能很容易地去诊断一些网络问题。
先看列表本身有哪些列。

列表的属性比较多,比如 Name、Status、Type、Initiator 等等,这个不难理解。当然,你还可以通过点击右键的下拉菜单来添加其他属性。
另外,你也可以按照列表的属性来给列表排序,默认情况下,列表是按请求发起的时间来排序的,最早发起请求的资源在顶部。当然也可以按照返回状态码、请求类型、请求时长、内容大小等基础属性排序,只需点击相应属性即可。
这里推荐一个很多人没注意的列:Initiator。它记录了这个请求是被谁发起的,鼠标悬停上去能看到完整调用栈。页面里冒出一个你不认识的请求,用它一秒定位到是哪个 SDK 干的。
选中列表中的任意一项,右边会出现这一项的详细信息。

你可以在此查看请求列表中任意一项的请求行和请求头信息,还可以查看响应行、响应头和响应体。然后你可以根据这些查看的信息来判断你的业务逻辑是否正确,或者有时候也可以用来逆向推导别人网站的业务逻辑。
排查接口问题的时候,我的习惯是先看 Status,再看 Request Headers 里的 Cookie 和自定义 token 头有没有带上,最后才看 Response。顺序反过来的话,你会对着一个 401 的响应体研究半天业务逻辑。
# 3.5 单个资源的时间线怎么读
了解了每个资源的详细请求信息之后,我们再来分析单个资源请求时间线,这就涉及具体的 HTTP 请求流程了。