我的性能测试骗了我:把第三方全拦掉再测
警告这篇是我自己的「打脸记录」:前面几篇性能文章里的数字,是在一个没有第三方脚本的平行世界里测出来的。真实场景要慢得多。
起因
为了写上一篇的对比,我跑了一次 Lighthouse:
Lighthouse 12.8 (mobile)
得分: 47 FCP 5.5s LCP 12.4s TBT 490ms
可我自己的脚本一直在报 LCP 1.9 秒。差 6 倍,必须查清楚。
三个”测量”,三个世界

| 数据源 | FCP | LCP | TBT | 请求 / 传输 |
|---|---|---|---|---|
| 我的 CDP 脚本 | 1.4s | 1.9s | 117ms | 41 / 59KB |
| Lighthouse simulate | 5.5s | 12.4s | 490ms | 83 / 1039KB |
| Lighthouse devtools | 3.5s | 12.1s | 1850ms | 83 / 1039KB |
请求数差一倍、传输差 17 倍。答案藏在我脚本的启动参数里:
args: ["--no-proxy-server",
"--host-resolver-rules=MAP * ~NOTFOUND , EXCLUDE blog.peroe.cn , EXCLUDE q2.qlogo.cn"]
这两行本来是为了绕开本机代理(用 CDP 限速时,代理会让连接超时)。副作用是:所有不在白名单里的域名都被解析成 NOTFOUND —— GA4、Clarity、Cookie 横幅、Umami、Giscus 全军覆没。
说白了,我这个脚本测的是「如果这个站没有第三方脚本,它有多快」。那当然快。
Lighthouse 说 LCP 是谁
更进一步,Lighthouse 直接告诉我们 LCP 元素是哪个:

LCP 元素: <p class="cc-nb-text" id="termsfeed-com---nb-text">
不是文章标题,不是卡片,是Cookie 横幅的说明文字。
时间线是:TTFB 1.76s → DOMContentLoaded → window.load → 横幅脚本(66 KB)异步插入 → 解析执行 → 渲染出那块大文本,大约 12 秒。
而 LCP 会一直记录到「用户首次交互」为止,所以这个晚出现的大块,直接把 LCP 顶到了 12 秒。
修了什么
最直接的一刀:别让横幅排在最后。它原来等 window.load 才加载,我改成 DOMContentLoaded 就加载(脚本本身仍是 async):
// 改前
window.addEventListener("load", load, { once: true });
// 改后
document.addEventListener("DOMContentLoaded", load, { once: true });
实测(Lighthouse devtools 模式):
| 改前(线上) | 改后(本地构建) | |
|---|---|---|
| 性能分 | 37 | 49 |
| FCP | 3.5s | 1.6s |
| LCP | 12.1s | 7.2s |
| LCP 元素 | 横幅文案 | 仍是横幅文案 |
还没解决的:横幅仍然是最大的元素
7.2 秒仍然远超 2.5 秒的「良好」线,而且 LCP 元素没变 —— 只要那块说明文字是页面上最大的元素、又是最晚出现的,它就会一直是 LCP。
两条路,都需要权衡:
- 把横幅做小:限制文字块宽度/行数(它现在是 351px 高的大块),让正文成为最大元素。风险是同意说明变得不明显。
- 换掉 TermsFeed:自建一个 2KB 的同意条。66KB 的第三方脚本 + 4 倍 CPU,只为了弹一条 Cookie 提示,性价比很低。风险是合规:条款文案、偏好中心、与 GA4/Clarity 的联动都要自己实现。
我倾向第二条,但它动的是合规相关的部分,需要你确认后再做。
三条教训
1. 测量脚本的”隐含条件”必须写下来。 我那行 host-resolver-rules 是三个月前为了修代理超时加的,早就忘了。它悄悄改变了被测对象。现在我在脚本头部固定写一行注释:「本模式会阻断所有第三方域名,只用于隔离自有资源的性能」。
2. 换一个工具复核。 同一个站点、同一台机器,Lighthouse 和我的脚本差 6 倍 —— 不是谁错了,是测的东西不同。两个数字都有价值,但必须知道各自的前提。
3. 永远看 LCP 元素是谁。 数字只是结果,「谁成为了 LCP」才是病因。这次如果不是 Lighthouse 告诉我那是 Cookie 横幅,我可能会去优化图片和字体。

小结
这轮的收获不是”优化了 5 秒”,而是发现自己的测量方法在骗自己。前面几篇里那些好看的数字(FCP 1.4s / LCP 1.9s / 41 个请求)都是真的,但含义是「排除第三方之后」——等于给站点做了一次「断网测试」。
真实场景的数字是:LCP 7.2s(横幅修好后)、TBT 1.5s、83 个请求 / 1MB。接下来的工作很清楚:把第三方从关键路径上撤下来,而不是继续优化我自己的 CSS。
同类的测量陷阱还有一次:和 Cookie 横幅抢 LCP里那三次尝试,有两招其实没用。
发现错误或想要改进这篇文章?
在 GitHub 上编辑此页文章修订历史 (1 次)
查看变更记录
docs(baseline): 第 30 轮终检——数字更新到最终状态,补第 28~30 轮小结
相关文章
- 和 Cookie 横幅抢 LCP:我试到哪一步就停了上一篇发现真正的 LCP 元素是 Cookie 横幅后,我试了三种办法:提前加载、压缩体积 75%、preload 脚本。性能分从 37 提到 50、FCP 从 3.5s 到 1.5s,但 LCP 卡在 7.4s 不动。这篇记下为什么压小体积没用,以及我为什么停在这里。
- 构建产物 16 MB,访客每次只下 28 KB统计 dist 目录发现 16 MB、313 个文件,其中 1.6 MB 的 Mermaid 图表引擎从来没被下载过。这篇把「部署体积」与「访客成本」分清:什么进了关键路径、什么按需加载、什么可以被缓存一年。
- 三层缓存各自为政:我的静态资源被一行 Cache-Control 拖慢浏览器缓存、Cloudflare 边缘缓存、源站响应头三层叠在一起时,谁说了算?抓自己站的真实响应头发现:连内容哈希命名的 CSS/JS 都是 max-age=0,每次访问都要重新验证。附发现过程、Cloudflare 规则写法和免费套餐的坑。