ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

DevTools 深度调试:Network、断点、性能与缓存排查实战

DevTools 深度调试:Network、断点、性能与缓存排查实战 1. 先把“devtool”这个词掰开揉碎写第二篇之前我想先花点篇幅把“devtool”这个词本身说清楚。因为我在群里见过太多次鸡同鸭讲的场面有人说“你打开 devtool 看一下”对方打开了浏览器 F12有人说“devtool 别配 eval”对方去点开了 F12 的 Console。同一个词指的根本不是同一个东西讨论自然不在一个频道上。这个系列的第一篇我聊的是最基础的部分——面板怎么打开、Elements 怎么改样式、Console 怎么打印对象。到了第二篇话题要往深处走网络请求怎么追、断点怎么下、卡顿怎么定位、缓存怎么清、真机怎么连。这些才是日常真正耗时的地方。如果你是从第一篇跟过来的恭喜基础操作已经够用了如果你是直接翻到第二篇的也没关系我会在关键处把前提条件补上不会出现“上回说到”这种让人抓狂的省略。这篇文章的目标读者有三类一是刚入行的前端或者测试同学写完了页面但一出问题就只会console.log二是工作两三年、能看懂 Network 面板但看不懂火焰图的同学三是需要做性能验收、要拿数据说话的技术负责人。三类人读同一篇侧重点不一样我会尽量把“怎么点”和“为什么这么点”都写上。我的核心主张就一句devtool 的价值不在于面板多而在于你能不能把一次线上问题在本地复现并且定位到具体那一行代码。面板是工具定位能力才是本事。往下看。1.1 三种“devtool”先认清你手上的是哪个这不是咬文嚼字选错了方向会浪费大量时间。平时提到 devtool绝大多数场景下指的是下面这三类之一。名称实际指代典型入口常见使用场景浏览器开发者工具浏览器内置的调试面板套件F12 / 右键检查 / 快捷键页面调试、接口抓包、性能分析、缓存排查构建工具的 devtool 配置项打包器里控制 source map 生成的字段配置文件中的devtool键决定产物是否带 source map、带哪种独立调试工具包某些运行时或框架提供的调试辅助模块依赖安装后按文档接入桌面端应用、特定运行环境的调试表格里第二行经常被忽略。比如打包配置文件里的devtool它跟浏览器的面板完全是两回事但如果两边配合不好你在 Sources 面板里看到的就是一堆压缩后的乱码。我个人的经验是开发环境让 source map 尽可能详细生产环境让它有但不能外泄源码内容具体配置我会在第 3 章展开。1.2 第二篇的定位从“看得见”到“查得出”第一篇解决的是“看得见”——元素在哪、样式被谁覆盖了、变量值是多少。第二篇解决的是“查得出”——这个请求为什么慢了 800 毫秒、这个点击为什么卡了两秒、用户说“页面白屏”到底是哪个资源挂了。我给自己定了个很土但很好用的判断标准如果你打开面板之后第一反应是“然后点哪里”说明你还在“看得见”的阶段如果你的第一反应是“我要先复现再看哪个指标异常”才算进入“查得出”。这个转变的关键是从“翻面板”变成“带着假设去翻面板”。比如用户反馈“列表页加载慢”你脑子里应该先冒出来几个候选假设接口本身慢接口快但渲染慢资源并行被阻塞了然后才去 Network 和 Performance 里找证据。带着假设查十分钟能定位不带假设翻半小时还在滑动时间轴。接下来的章节顺序也遵循这个逻辑先看数据是怎么来的Network再看代码在哪里断的Sources然后看时间花在哪了Performance接着看数据存在哪了Application最后看真机和自动化怎么接。每一章我都会给出可以直接抄的操作路径以及我踩过的坑。2. Network 面板把请求链路看透Network 面板大概是所有人打开频率最高的面板但真正把它当“诊断仪”用的人不多。多数人只做一件事看某个接口返回了什么。这太浪费了。它其实是一条完整的链路观测窗口从浏览器决定发起请求到收到最后一个字节中间每一步的耗时都能被拆开。能拆开才能定位拆不开就只能靠猜。2.1 三个必开的开关和一次正确的抓包姿势打开 Network 之后先别急着刷新有几件事要提前做。勾选Disable cache禁用缓存在面板顶部工具栏。这一步极其关键。不勾的话你看到的一堆200 (from disk cache)或者304耗时全是假的会让你误判接口很快。我在做首屏优化的时候就因为忘了勾这个得出过“接口只要 20 毫秒”的错误结论实际冷启动是 600 多毫秒。勾选Preserve log保留日志。页面一旦跳转不勾这个之前的请求记录会被清空。排查登录跳转、支付回调这类流程时这个选项是刚需。反过来日常调试页面刷新时它会把历史记录堆得乱七八糟所以我一般是单页调试关掉流程追踪打开。打开Throttling网络限速。默认是 No throttling我建议至少在用 4G 档位Fast 4G 或 Slow 4G过一遍。你在本机千兆宽带下测出来的 1.2 秒加载在用户的地铁 4G 上可能就是 5 秒。很多“本地好好的线上一堆投诉”的问题都出在这里。限速之后如果发现某个资源的体积占比特别扎眼优化的方向自然就出来了。注意限速只影响网络请求不影响 CPU 计算。判断页面卡不卡还得配合 Performance 面板的 CPU 降速两件事不要混为一谈。2.2 瀑布图里那几段颜色到底谁在拖时间请求列表右侧有个时间线鼠标移上去会展开一个浮层把这段耗时拆成若干阶段。很多人看到英文就划走了其实就那么几段阶段含义通常偏大的原因Queueing / Stalled排队等待并发连接数用满、被更高优先级请求插队、浏览器在等磁盘缓存DNS Lookup域名解析解析耗时高、没有预解析、域名层级太深Initial connection建连服务端响应握手慢、地理位置远TLS setup安全连接协商证书链过长、没有会话复用Request sent发送请求请求头过大、带了过多 CookieWaiting (TTFB)等首字节服务端处理慢、数据库慢、CDN 回源Content Download下载内容响应体太大、压缩没开、带宽被抢占看这张表有个经验法则TTFB 大基本是服务端的事Content Download 大基本是响应体的事Stalled 大说明你的资源编排有问题。这个判断能帮你快速把责任范围缩小一半。我有一个项目首页有个 3MB 的图片TTFB 只有 80 毫秒Content Download 却占了 4 秒多改图压缩加懒加载之后首屏时间直接砍掉一半多。这种问题不需要看火焰图看颜色条长度就够了。另外一个容易忽略的点是Waterfall 的顺序。资源请求是瀑布式下发的如果某个关键 JS 阻塞了后面所有资源的解析比如它在 head 里同步加载还带着一堆依赖你会看到明显的一级一级的阶梯。阶梯越陡越长说明串行依赖越深。2.3 过滤语法比手滑快十倍请求一多靠肉眼看列表就是自虐。Network 面板的过滤输入框支持一套类似搜索语法的写法用熟了效率差好几个档次。domain:api.example.com—— 只看某个域名的请求排查跨域、CDN 回源特别实用status-code:500—— 只看报错请求前面加个减号-status-code:200就是排除正常请求method:POST—— 只看写操作排查重复提交时必用larger-than:200k—— 只看大体积资源找体积瓶颈的起手式mime-type:application/json—— 只看接口返回挤掉图片和脚本has-response-header:cache-control—— 只看带缓存头的响应排查缓存策略is:from-cache—— 只看命中缓存的请求验证缓存有没有生效多个条件之间用空格连接表示“与”的关系。我排查故障的固定套路是先status-code:过滤出异常再用domain:缩小到具体服务最后用larger-than:确认是不是体积问题。三步走完八成的问题已经有方向了。提示不确定语法对不对可以在输入框里打一个关键词下拉会自动提示可用的筛选项。别硬背。2.4 右键那几项能省掉你一半的手工活列表里任意请求上右键菜单里有几个功能值得单独说。Copy as cURL把这次请求完整复制成一条命令行。我经常用它做两件事——一是丢给后端同事说“你本地跑一下这条看返回是不是也慢”二是拿去在终端里反复执行验证是不是偶发问题。比截图高效得多。Copy as fetch生成一段等价的 fetch 代码直接可以贴到 Console 里重放。排查需要特殊请求头、特殊鉴权的问题时特别顺手。Save all as HAR with content把整个会话导出成一个 HAR 文件。这个文件能拖回任意一台机器的 Network 面板里回放。做性能验收留档、给异地同事复现问题时这是标准做法。我现在的习惯是每次性能验收都导一份 HAR存档加时间戳回头对比不同版本的差异比拍脑袋回忆靠谱多了。3. Sources 面板断点调试的正确打开方式console.log不是不能用但它有几个硬伤改一次要重新构建或者刷新、不能在中间检查调用栈、打印大对象还要手动展开。调试到一定复杂度断点是唯一解。而且断点的种类比大多数人以为的多得多。3.1 断点全家桶什么时候该用哪一把先把清单摆出来再逐个说场景。断点类型触发时机典型用途行断点执行到指定行最基础看变量值条件断点满足表达式才停循环里只抓某一次日志断点打印后继续执行不想改代码又想看值DOM 断点节点被修改/删除排查“谁动了我的 DOM”XHR 断点匹配的请求发出找出请求是在哪段代码里发的事件监听断点指定事件被触发排查重复绑定、事件冒泡异常异常断点抛出异常时暂停抓“报错但不知道哪报的”条件断点是我用得最多的一种。在一个跑一万次的循环里找第 8732 次的问题普通行断点会让你点到怀疑人生。做法是行号上右键选添加条件断点写下类似index 8732或者item.id xxx的条件。条件满足才停一次到位。日志断点有的版本叫 logpoint解决的是另一个场景你想知道某个变量在每次循环里的值但不想改代码、不想断下来。它会在 Console 里打印你写的表达式然后自动继续。生产环境排查线上灰度代码时这种“不侵入”的方式特别有价值。DOM 断点值得单独提一句。你有没有遇到过“页面上的元素莫名其妙消失了”或者“样式被改了但找不到是谁改的”在 Elements 里选中那个节点右键选择断开条件——子树修改、属性修改、节点移除三种。触发的瞬间会切换到 Sources调用栈整整齐齐摆在那里。我用这招抓过一次“某个第三方脚本偷偷把我方容器的 class 改掉”的问题半小时的猜测变成两分钟的定位。事件监听断点在 Sources 面板右侧的 Event Listener Breakpoints 里展开。找重复绑定事件的 bug 时勾上 click 或者 scroll触发时看调用栈里的函数名谁绑的一目了然。3.2 断下之后别只盯着那一行断点停下来之后右侧面板有三块信息价值比那一行代码大得多。**Call Stack调用栈**告诉你“我是怎么走到这里的”。从下往上读最下面是入口最上面是当前执行点。我排查“某个函数被意外调用”时第一眼看的就是调用栈里有没有不该出现的函数名。**Scope作用域**分三块Local 是当前函数的局部变量Closure 是闭包捕获的变量Global 是全局对象。很多“变量值怎么跟我预期不一样”的困惑答案就在 Closure 里——被闭包引用的变量比你想的活得久。**Watch监视**可以把任意表达式固定住每次断下自动求值。像user.id、list.length这类关键字段加进 Watch 就不用来回在 Console 里敲了。顺带说两个懒人技巧在 Console 里用$0可以直接引用 Elements 面板当前选中的节点$_是上一次执行的结果copy(某对象)能把对象内容直接复制到剪贴板。写调试脚本时这三个省事很多。3.3 Local Overrides不改源码也能试方案这个功能知道的人不多但用过就回不去。它的作用是你可以在 Sources 面板里直接编辑线上加载的 CSS 或者 JS 文件改动保存在本地刷新页面依然生效。典型场景线上有个样式错位你想验证“把宽度从 100% 改成 auto 是不是就好了”但改源码要走提测流程。用 Local Overrides在 Sources 里找到那个文件改成你想要的样子保存刷新效果立刻可见而服务器上的文件分毫未动。操作路径是打开 Sources切到 Overrides 面板点“选择文件夹”授权一个本地目录然后编辑任意文件时 DevTools 会提示把改动保存到该目录。注意这个目录别用桌面或者下载文件夹容易被误删我一般建一个项目同级的.devtools-overrides目录加进忽略列表。注意Overrides 的内容不会自动同步给团队也不会进版本库。它只是你本地的“试验田”验证完结论记得把真正的改动落到代码里否则很容易出现“我本地看着好好的啊”这种乌龙。3.4 source map 和构建配置让断点落在源码上很多人第一次用打包后的项目调试时会看到一堆变量名变成了单个字母函数体挤成一行。这不是 DevTools 的问题是构建产物的问题。关键就在构建配置里的devtool字段。配置取值生成方式适用环境说明eval-cheap-module-source-map每个模块内联开发重建快能定位到源码行eval-source-map内联完整映射开发信息全但体积大、构建慢source-map独立.map文件生产信息完整需自行控制访问权限hidden-source-map独立文件但不挂引用生产想上报错误又不暴露入口时用nosources-source-map只映射行列不含源码生产能定位位置看不到原始代码开发环境的推荐配置大概是这样的// 构建配置片段开发环境 module.exports { mode: development, devtool: eval-cheap-module-source-map, // 其余配置省略 };生产环境我一般用hidden-source-map把生成的映射文件上传到错误监控平台页面上不挂sourceMappingURL注释。这样既能收到带源码行号的报错又不至于让任何人打开面板就能看到完整源码。这一步的取舍逻辑很简单开发要快生产要准但要藏。4. Performance 面板别再用 console.time 猜了console.time能告诉你一段代码跑了多久但它说不清时间花在哪。Performance 面板能。它记录的是整个页面在这段时间内的所有活动——脚本执行、样式计算、布局、绘制、内存变化——然后按时间轴铺开。第一次看会晕但阅读顺序其实很固定。4.1 录制前的清场工作录制之前必须做几件事否则录出来的数据几乎没法用。第一用无痕窗口或者至少关掉所有扩展。扩展会往页面里注入脚本录出来的火焰图里会混进一堆不属于你项目的函数。第二开CPU 降速。主机 CPU 太快很多只在低端机上出现的问题录不出来。我一般降到 4 倍或 6 倍相当于模拟中低端安卓机的算力。这一步跟 Network 的限速是两码事别搞混。第三清空缓存并强制刷新然后等页面稳定下来再开始录制。首屏录制的起点如果是“正在加载”火焰图会非常凌乱。第四明确你要录什么。是首屏加载、是某次点击响应、还是滚动过程中的卡顿录制时间越短数据越干净。我见过有人录了 30 秒的连续操作结果分析了两小时还没找到重点。4.2 火焰图的阅读顺序先看指标再找长任务录完之后面板大致分成几块顶部的 FPS 条、CPU 占用条、中间的火焰图、底部的 Summary / Bottom-Up / Call Tree / Event Log 四个视图。我的固定阅读顺序是先看FPS 条。绿色说明帧率稳定红色说明掉帧。如果整条都是红的问题基本在渲染或者脚本阻塞不用急着往下翻。再看CPU 条。黄色是脚本执行紫色是渲染和布局绿色是绘制灰色是系统任务。黄色的块又长又密说明 JS 是大头去看火焰图里的长任务紫色的块多说明布局抖动或者样式计算频繁。然后找长任务。火焰图里带红色小三角标记的区块就是执行超过 50 毫秒的任务。50 毫秒是浏览器保持 60 帧的预算上限超过它就有掉帧风险。找到最长的那个点开看里面的函数调用。最后用Bottom-Up视图排一次序。它按“自身耗时”从大到小排列能直接告诉你哪个函数最该优化。火焰图看到的是调用关系Bottom-Up 看到的是责任归属两个配合用。4.3 三个我真实踩过的卡顿案例案例一长列表一次渲染 5000 个节点。火焰图里出现一个 1.8 秒的长任务展开之后全是渲染函数的递归调用紫色的 Layout 块紧跟着一大片。改法很直接虚拟列表只渲染可视区域长任务从 1.8 秒降到 40 毫秒以内。判断依据如果在火焰图里看到 Scripting 之后紧跟着巨大的 Recalculate Style 和 Layout基本可以确定是 DOM 操作过多。案例二滚动时反复读取布局属性导致重排。表现是滚动卡顿但单次操作都不慢。用 Performance 录制滚动过程会发现无数个小的紫色块密集堆叠。原因是在循环里交替读写样式属性触发了强制同步布局。改法是先把所有需要读的值一次性读出来缓存再统一写。案例三解析一个 4MB 的 JSON 阻塞主线程。火焰图里有个平坦的大块展开是 JSON 解析相关调用。这种问题的解法不是优化解析速度而是换思路要么让后端分页返回要么把解析放到后台线程里做要么直接换成更紧凑的数据格式。优化的第一步往往是改数据量而不是改算法。4.4 顺手的两个搭档Coverage 和 LighthousePerformance 面板旁边还有两个工具值得一起用。**Coverage代码覆盖率**在更多工具里能找到。它统计页面加载过程中JS 和 CSS 里有多少字节真正被执行了。我见过的一个真实情况是首屏引了一个 600KB 的工具库实际只用到其中一个函数覆盖率显示 4%。这种数据比任何文字说明都有说服力拿它去推动代码拆分特别有效。Lighthouse给的是一份体检报告分数只做参考我更关注它列出的具体机会点——比如“移除未使用的 JavaScript 可以省 XXX 毫秒”“图片没有设置明确尺寸”。这些是可执行的清单比一个总分有用得多。提示Lighthouse 的跑分受环境波动影响很大同一份代码连跑三次可能差十几分。别拿单次分数下结论看趋势和具体建议项。5. Application 面板与存储排查页面上的问题有一部分根本不在代码里而在存储里。缓存了旧数据、localStorage 写满了、Service Worker 拦了请求——这些现象在代码层看都很诡异但在 Application 面板里一目了然。5.1 Storage 一览先看存量再看格式Application 左侧的 Storage 区域列出了所有本地存储Local Storage、Session Storage、IndexedDB、Cache Storage、Cookies。排查时我的第一反应是看“存量对不对”第二反应是看“格式对不对”。存量不对常见原因是写入了超大对象没清理。Local Storage 单个域名的容量通常在 5MB 左右写满之后继续写会直接抛异常。如果你在 Console 里看到QuotaExceededError基本就是这个原因。解法是给缓存加上过期时间和容量上限别把 Local Storage 当数据库用。格式不对通常是因为存进去的时候是对象读出来的时候期望是字符串或者 JSON 解析失败。调试时我习惯直接在编辑区改值双击任意条目就能编辑改完刷新立即生效。验证“某个功能是不是读的某个缓存值”时这招比改代码快得多。IndexedDB 稍微麻烦一点数据量大时展开会卡。真要查具体内容我一般是在 Console 里用indexedDB相关 API 加条件查询或者用面板里的刷新按钮先看一眼对象仓库结构再决定查哪张表。5.2 Service Worker缓存不更新时先来这里“我明明改了用户还是看到旧页面”——这句话背后十有八九是 Service Worker 或者 Cache Storage 在作祟。排查顺序是固定的先看 Application 里的 Service Workers 列表确认当前页面的控制器状态。常用操作有三四个勾选 Offline 模拟断网、点 Update 强制检查更新、勾选 Bypass for network 让请求绕过缓存直接走网络。日常调试我用得最多的是最后一个加上它之后所有请求都直连服务器能立刻判断问题是不是缓存引起的。再看 Cache Storage 里存了哪些资源、版本号是什么。命名规范的项目缓存名里带版本号一眼能看出用的是不是最新版。如果缓存名没变但内容变了那就是更新策略写错了。清理的动作要谨慎。不要轻易点 Unregister注销尤其是在生产环境调试时注销会让当前用户直接失去离线能力。想快速验证先清 Cache Storage 再看效果注销放到最后。5.3 Cookie 属性与跨域调试要点Cookies 表格里我最常看两列HttpOnly和SameSite。前者决定了这个 Cookie 能不能被脚本读取后者决定了跨站请求会不会带上它。定位“登录状态莫名丢失”时这两列的信息量最大。如果发现了接口请求里没带上 Cookie按这个顺序检查Cookie 是否存在、是否过期、SameSite是不是被设成了严格模式、请求是不是跨站、协议和域是否匹配。这五步走完问题基本就出来了比在后端日志里翻半天高效。注意在面板里手动修改 Cookie 值只对当前会话有效刷新或跳转可能就没了。用它验证假设可以别用它当“永久修复”。6. 移动端、远程调试与自动化采集前面几章讲的都是在桌面浏览器上折腾。真实场景里至少要覆盖移动端和批量数据采集两个方向。6.1 设备模拟方便但有边界设备模拟Device Toolbar能切换屏幕尺寸、像素比、UA 字符串。做响应式布局的时候它是主力工具。但我必须提醒一句模拟不是真机。屏幕尺寸和 UA 能骗过去但触控事件、真实的 GPU 渲染性能、字体渲染差异、系统级别的滚动惯性模拟都还原不了。我的用法是布局和样式在模拟器里调性能和交互必须真机验证。尤其是 iOS 上的惯性和安卓上的输入框键盘顶起问题模拟器里根本复现不出来。6.2 真机远程调试把手机接到桌面面板上这一步的前提是手机和电脑在同一个局域网内手机开启调试模式数据线连上或者通过调试地址配对。连上之后桌面端会出现设备列表点开就能看到手机上正在运行的页面并且可以在桌面端操作 Elements、Console、Network就像调试桌面页面一样。Network 面板里能看到手机发起的真实请求和真实耗时这个数据比模拟限速更可信。实操中遇到的坑主要有两个一是手机浏览器版本和桌面浏览器版本差异太大导致面板功能不了解决办法是尽量保持版本接近二是某些定制系统对调试模式有限制需要额外开关。6.3 用脚本批量采集性能数据手动录一次两次还行要做回归对比就得靠脚本。下面这段是基于浏览器自动化接口采集核心指标的思路参数按自己项目实际情况替换。// 采集一次页面加载的核心性能指标 const puppeteer require(puppeteer); async function collect(url) { const browser await puppeteer.launch({ headless: new }); const page await browser.newPage(); // 模拟中低端移动设备保证数据有参考价值 await page.emulate({ viewport: { width: 390, height: 844, deviceScaleFactor: 3, isMobile: true }, userAgent: Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) Mobile }); // 采集绘制相关的关键时间点 await page.evaluateOnNewDocument(() { window.__marks {}; new PerformanceObserver((list) { for (const entry of list.getEntries()) { window.__marks[entry.name] entry.startTime; } }).observe({ entryTypes: [paint, largest-contentful-paint] }); }); await page.goto(url, { waitUntil: networkidle0 }); const metrics await page.metrics(); const marks await page.evaluate(() window.__marks); await browser.close(); return { marks, metrics }; } collect(https://example.com).then((r) console.log(r));这段脚本能拿到几个关键数据首次绘制时间、最大内容绘制时间以及指标对象里的布局次数、样式重算次数、JS 堆占用。其中布局次数和样式重算次数特别值得盯——如果它们异常高说明页面存在布局抖动配合前面的 Performance 面板能直接对上。把采集逻辑接进持续集成流程里每次发版跑一次把结果存起来做趋势对比。单次数据说明不了什么趋势才能说明问题。我现在的做法是每周固定跑一次数据落库页面一有异常波动就能第一时间发现。7. 常见问题速查与避坑清单最后这部分是纯经验都是我这些年在排查现场攒下来的。按“现象—原因—动作”的方式整理遇到问题可以直接对号入座。现象大概率原因第一步动作本地改的样式被覆盖选择器优先级不够或有内联样式在 Elements 里看 Computed 面板的最终来源请求耗时全是几十毫秒但页面就是慢缓存命中耗时数据失真勾上 Disable cache 重新录制断点打上了但不生效代码是压缩产物源码映射没配好检查构建配置里的映射选项火焰图里 FPS 一直红主线程被长任务阻塞找超过 50 毫秒的任务用 Bottom-Up 排序页面刷新后改动消失只改了 Elements 没做持久化用本地覆盖功能保存改动接口返回对但页面显示旧数据前端缓存或 Service Worker 拦截在 Application 里清 Cache Storage真机调试连不上不在同一网络或调试开关未开检查网络、调试模式、连接状态关于避坑我特别想说三条。第一条别在没复现的情况下开面板。复现是调试的地基。如果只看到用户截图你先要问的是“什么设备、什么网络、什么时间点、做了什么操作”把场景尽量还原再打开面板。直接开面板翻来翻去效率极低。第二条一次只改一个变量。我见过有人排查慢加载时同时开了缓存禁用、加了限速、又改了并发数最后得出“优化无效”的结论其实变量都混在一起了。定位问题要像做实验一样控制变量。第三条把结论写下来。我现在的习惯是每次排查完在笔记里留三条现象是什么、根因是什么、验证方式是什么。下次遇到同类问题翻笔记比重新排查快得多。DevTools 的功能更新很快但排查的逻辑十几年没变过积累的是逻辑不是按钮位置。再补一个容易被忽略的小功能Console 里的debug(函数名)和monitor(函数名)。前者等价于给这个函数下一行断点后者会在每次调用时打印传入参数。想快速看某个工具函数被调了多少次、参数是什么一行命令搞定比翻 Sources 找位置快。最后分享一个我最近用得比较多的组合拳先用 Coverage 找出没被执行到的代码把包拆掉再用 Performance 录一遍确认长任务消失了最后用脚本采集一轮数据存档。三步下来一次优化能拿出前后对比的硬数据无论是过评审还是写复盘都比“感觉快了不少”有说服力。这套流程我跑了小半年最大的感受是devtool 真正的门槛从来不在面板本身而在于你有没有一套稳定的、可重复的排查方法。面板会改版方法不会。
返回列表