reduce unused javascript:32 个首页里 29 个在跑自己用不到的代码
reduce unused javascript 是 Lighthouse 那条审计:量每个下载回来的脚本里,浏览器根本没执行的字节。32 个首页各跑一次,中位数的站带了 347 KB,其中近三分之二来自三方脚本,另有三个首页一条都没被标记。

实测 · 2026-10-02 · 32 个首页 · 单次 Lighthouse
样本 / 口径:尝试 34 个首页(2026-08-15 起一直用的那 30 个站,加我们自己的 4 个),2026-10-02 各用 Lighthouse 13.x 的移动端配置加载一次,读每份 JSON 报告里的 unused-javascript 审计。两个被剔除——railway.com 没产出报告,www.shopify.com 撞上 protocol timeout——剩 32 个。每站一次,不平均,不重跑。
reduce unused javascript 是 Lighthouse 那条审计,量的是每个下载回来的脚本里、浏览器压根没执行的字节。32 个首页各跑一次,29 个至少带一条这样的脚本。中位数的站带了 347 KB 从没跑过的代码,最多的一个带了 1.4 MB,另有三个首页一条都没被标记。
怎么测的
这条审计就是 Lighthouse 里标题写作 "Reduce unused JavaScript" 的那条,它靠的是 V8 的代码覆盖率,不是靠体积猜。对页面加载的每个脚本,它给两个数:传输了多少字节,以及到这次运行结束为止、其中多少字节从没被执行过。两者的差就是它报出来的浪费。
我们每个域名跑一次无头 Lighthouse,只开这一条审计,直接读 JSON 里的逐脚本数值,再按站把浪费加起来。我们没有对任何一个站重跑,也没有改动页面。因为这台机器所在地的关系,有几个域名把我们重定向到了本地化路径——developer.mozilla.org 落到 /zh-CN、slack.com 落到 /intl/zh-cn、canva.com 落到 /zh_cn、stripe.com 落到 /nl、我们自己的 querywin.com 落到 /zh——我们保留了重定向后的那一份。
reduce unused javascript:32 个首页里 29 个中招
三个首页回来时没有任何可报的东西:Astro 的营销站、MDN、Hacker News。其余每一个域名都至少有一条被标记的脚本,前四名各自带着超过 1 MB 从没跑过的代码。下表是全样本,从多到少,单位 KB。
| 首页 | 未用 JS (KB) |
|---|---|
| www.theverge.com | 1,382 |
| www.nytimes.com | 1,371 |
| www.wired.com | 1,179 |
| webflow.com | 1,147 |
| techcrunch.com | 886 |
| github.com | 863 |
| stackoverflow.com | 728 |
| substack.com | 715 |
| arstechnica.com | 660 |
| www.netlify.com | 577 |
| discord.com | 571 |
| slack.com | 536 |
| www.cloudflare.com | 517 |
| medium.com | 513 |
| vercel.com | 384 |
| www.bbc.com | 384 |
| supabase.com | 310 |
| sizemarker.com | 308 |
| www.framer.com | 307 |
| figma.com | 298 |
| linear.app | 277 |
| querywin.com | 275 |
| biaojixia.com | 247 |
| www.canva.com | 223 |
| stripe.com | 214 |
| byerisk.com | 185 |
| www.reddit.com | 178 |
| www.notion.com | 98 |
| en.wikipedia.org | 97 |
| astro.build | 0 |
| developer.mozilla.org | 0 |
| news.ycombinator.com | 0 |
形状是长尾加重头。分档看,四个首页带着超过 1 MB,四个低于 200 KB,另有三个一条都没标记。347 KB 这个中位数只是浪费——被抓来又没跑的那部分——还没算上页面脚本真正执行掉的那些。
| 未用 JS | 站数 |
|---|---|
| 1 MB 以上 | 4 |
| 500 至 1000 KB | 10 |
| 200 至 500 KB | 11 |
| 200 KB 以下 | 4 |
| 没有标记 | 3 |
未用的 JavaScript 不是你一眼能看见的赘肉。页面照常渲染,代价只是访客为一段从没跑过的代码付了下载和解析。
浪费从哪儿来
按来源拆,大约三分之二的浪费字节——15,430 KB 里的 9,977 KB——来自站点自有域名以外的脚本,这还是在把子域名算作一方之后。最清楚的一个例子是 Google 的 reCAPTCHA:同一个挂件在好几个互不相关的域名上排进前列,每个大约 250 KB 未用 JavaScript,因为页面把整份国际化脚本都装了进去,只用到其中一小部分。
| 脚本 | 站点 | 浪费 |
|---|---|---|
landing-pages.js | github.com | 414 KB |
vendor.js | www.nytimes.com | 288 KB |
5441.js | www.wired.com | 257 KB |
recaptcha__zh_cn.js | webflow.com | 250 KB |
recaptcha__en.js | www.netlify.com | 247 KB |
gtm.js | www.theverge.com | 231 KB |
index-consolidated.js | discord.com | 224 KB |
两条规律贯穿着这张表。第一,三方标签占了浪费的一大块,而且最难拿掉,因为你很少能决定它们运多少东西过来,它们还会在你脚下变。一个 755 KB 的标签管理器、一个每页花掉四分之一兆的验证码,是别人做的决定、你来买单。第二,一方打包同样在浪费:纽约时报的 vendor 块和 Wired 的段落包各自约四分之一兆,首屏根本碰不到。两条都没有一行命令能解决的修法,这是这张表里最实在的话。
这对你意味着什么
你自己的数字一条命令就有,不用账号、不用注册。
npx lighthouse https://example.com/ \
--only-audits=unused-javascript \
--output=json --output-path=ujs.json --quiet
- 对首页跑一次,再挑一个重的内页跑一次。首页和文章页浪费 JavaScript 的位置不一样
- 先看三方那几条。它们往往是你不改自己构建就能删掉或推迟的
- 把这个数字当下限。它只算到运行时还没执行的代码,真实访客触发的交互它没算进去
- 别为了压这个数字去删你没法确认没用的代码。覆盖率量的是这一次运行,不是应用里的每一条分支
- 别以为框架的代码分割已经替你解决了。Wired 和纽约时报都做了分包,两家还是排在最前面
如果你想看同一批脚本在首屏之前花了多少时间,那是另一笔账:render blocking resources 讲顺序那一半,async defer 实测 27 个首页 讲脚本怎么加载,它们烧掉的主线程时间在 total blocking time 实测 里。
这些数字没有告诉你什么
三条边界,第一条最要紧。这条审计只算到运行停止时还没执行的代码。一个真实访客不会触发的脚本——一个弹窗、一段结算流程、一个后台入口——在这里看起来是完全没用的,哪怕每天都有一小部分访客在用它。这是下限,不是判决。
第二,「没有标记」不等于零未用。Lighthouse 只列超过上报阈值的脚本,所以一个由好几个小文件拼成、每个只部分未用的站,可能干干净净地回来。表里那三个零是好结果,但这一次运行分不出 Astro、MDN、Hacker News 是真的一个字节都不浪费,还是只是没有大到能上榜的文件。线以下我们没测。
第三,这是每站一次实验室运行、单次快照。覆盖率对重跑是稳的,比加载耗时稳得多,但它描述的仍是 2026-10-02 那天、在这台机器上、还带着部分本地化重定向的那一版首页。单次读数当方向,别当分数。
常见问题
你们是怎么测的?
2026-10-02 每个首页跑一次无头 Lighthouse,移动端配置,从 JSON 里读 unused-javascript 审计。不重跑,不平均,不用 field 数据。样本是 32 个同类型页面——首页,其中包含我们自己的四个站。34 个尝试里有 2 个被剔除,名字写在方法那一段。
怎么找出自己站上的未用 JavaScript?
跑上面那条命令,或者打开 Chrome DevTools 的 Coverage 面板,它显示的是同一份数据、实时更新。审计给你数字和文件清单,DevTools 让你点开某个文件、看清哪些行从没跑过。从最大的那条三方脚本开始,因为删掉它通常不动构建。
未用 JavaScript 影响 SEO 吗?
不直接影响。没有一个排名信号叫「未用字节」。它的意义是给加载和主线程加的那份成本,最终体现在 Core Web Vitals 上——主要是 largest contentful paint 和 interaction to next paint。把它当成性能输入,不是排名字段。
未用 JavaScript 和 render blocking 是一回事吗?
不是。render blocking 讲的是顺序——一个脚本不下载完,页面就不画。未用 JavaScript 讲的是体积——代码到了,却没跑。一个脚本可以加了 defer、完全不挡渲染,照样浪费四分之一兆。两个不同的问题,两套不同的修法。
三方脚本为什么浪费这么多?
因为它们要能在每一个嵌入它的站上工作,于是把每一条分支、每一种语言都打进一个文件,让页面只用其中一小部分。这批里那个国际化的 reCAPTCHA 就是原型:一个文件、很多语言、页面只需要其中一种。你通常没法把它削小,只能决定它还该不该待在这个页面上。
下一步
这个数字好拿,也难反驳。拿你自己的那一份,先把三方那几条排前面,逐条问一句——没有它,这个页面还干不干得成它该干的事。盯着你发出去的代码里到底有多少真的跑起来,正是 QueryWin 在做的事。


