第三方脚本拉进8个域名,只看HTML一个都看不到

第三方脚本拉进8个域名,只看HTML一个都看不到
张文保 21 分钟阅读 3,592 阅读
本文目录
  1. 只读HTML,你能看到几个第三方?
  2. 1和8的差距
  3. 为什么这件事值得单独说
  4. 把第三方全部掐断,页面还剩什么?
  5. 实验怎么做的
  6. 先说一次尺子失效
  7. 正文基本还在
  8. 骨架一条不少
  9. 图片是唯一真塌的那一项
  10. 462个域,为什么两个站几乎不重合?
  11. 三分之二只出现一次
  12. 0.051这个数
  13. 权威大样本为什么看不到这条长尾
  14. 这些外部域,分别在干什么?
  15. 分类结果
  16. 最大的那一类,是“归不了类”
  17. 字节和数量完全不是一回事
  18. 一半的字节,不是你发出去的
  19. 中位数39.1%,四分之三分位90.7%
  20. 累计字节最大的那个域,跟你想的不一样
  21. 字节和抓取的关系
  22. 那这些第三方,会不会真的挂?
  23. 实测这一刻,基本都是活的
  24. 真正的风险在三个别的地方
  25. 这份清单该由谁来盘?
  26. 每一个都是有人添的,加起来没人认领
  27. 盘点的正确姿势是按域,不是按脚本
  28. 盘完之后,哪些该动哪些不必
  29. 先按三个维度排一遍
  30. 把掐断测试做成常态检查
  31. 常见问题解答
  32. 第三方域多是不是就一定不好?
  33. 为什么只读HTML看到的第三方那么少?
  34. 掐断第三方之后图片全没了,这算问题吗?
  35. 行业整理的第三方脚本清单能直接用吗?
  36. 那些大规模统计报告的数字,跟自己测出来的对不上怎么办?
  37. 第三方经常挂吗?
  38. 用内容安全策略把第三方管起来,可行吗?
  39. 这次的数字能不能套到我的站上?
  40. 权威参考资料

摘要:131个海外独立站的首页,只读HTML的时候能看到的外部域名中位数是1个;等脚本跑完,这个数变成8个,最多的一个站41个。26个站(20.5%)从“看起来只依赖两三家”变成“实际连着十五家以上”。把所有第三方请求全部掐断再跑一遍:正文中位数还剩94.6%,链接和结构化数据几乎一条不少,但图片只有5.5% 能加载出来,78.4% 的站七成以上的图挂掉。更值得记的是那462个不同的第三方域——其中295个只出现在一个站上,任取两个站,它们的第三方清单重合度平均只有0.051。

做前两篇实测的时候,网络面板一直在旁边开着。有个画面反复出现:地址栏里是一个域名,请求列表里是二三十个。

这件事本身不新鲜,做前端的都知道页面会加载外部资源。真正让人想量一量的是另一层:这些依赖,在你只读HTML的时候,几乎一个都看不出来。

这是同一批数据的第三个侧面。前两篇分别问的是“不执行脚本还剩多少内容”和“执行完之后用户能看到多少”,答案见关掉脚本之后还剩多少字的实测隐藏内容的可读性裁决表。这一篇问的是:页面跑起来的时候,到底有多少家外部公司参与其中。

只读HTML,你能看到几个第三方?

先把口径说清楚。这里的“第三方”指的是与站点主域不同的注册域(也就是常说的顶级域加一级),子域不算,比如 cdn.example.com 仍然算自己家的。这个口径偏保守,会把不少实际由外部公司运营的资源算成第一方。

1和8的差距

同一批站跑两轮:一轮把脚本关掉,一轮让它正常执行,其余条件全部相同。数出每轮实际发生请求的外部域名个数。

指标关掉脚本脚本跑完
第三方域数中位18
全站请求数中位50129

脚本给页面新增的第三方域,中位数是6个,最多的一个站新增38个。

更能说明问题的是这组:有26个站(20.5%)在只读HTML时最多只能看到2个外部域,脚本跑完之后变成15个以上。brooklinen从1涨到33,graza从1涨到30,reebok从1涨到29,ice-watch从0涨到23。

为什么这件事值得单独说

因为大量安全与合规检查是在HTML层做的:扫一遍源码里的 <script src>,列出外部域,做成一份依赖清单。这个做法在十年前是够用的。

现在不够了。一个标签管理器、一个应用市场的插件加载器,本身只占HTML里的一行,跑起来之后会按配置去拉十几个别的域。那一行代码是你审过的,它拉进来的十几个域不是。

这种“一行代码带进一串依赖”的模式,web.dev关于第三方JavaScript的说明里讲得比较系统:外部脚本除了自身体积,还会带来额外的连接建立、执行阻塞和后续请求,而这些成本在引入的那一刻通常没人算过。

依赖清单的分布也印证了这一点:

第三方域数站数占比
0到1个43.1%
2到5个3326.0%
6到10个3729.1%
11到20个2721.3%
21个以上2620.5%

分母127。四分之一分位是3个,四分之三分位是16个,最多的一个站41个。

把第三方全部掐断,页面还剩什么?

知道有多少个依赖之后,下一个问题自然是:万一它们不在了呢。这个问题不用等意外发生,可以直接造出来。

实验怎么做的

在浏览器里给每个站装一条路由规则:凡是目标域与站点主域不同的请求,一律中断。然后正常访问首页,等3.5秒,量正文、链接、图片、结构化数据。

这个做法模拟的不是“某一家第三方挂了”,而是一个极端场景:所有外部依赖同时不可达。现实里更常见的是其中一两家慢或者挂,但极端场景能把依赖的骨架照出来。

先说一次尺子失效

第一版跑完的结果是:33.6% 的站掐断第三方之后连页面都打不开。这个数字很吓人,差点就写进结论了。

去看失败原因才发现分成两类。一类是超时,那是真的;另一类的错误信息长这样:请求主文档时直接失败,而这些站的最终地址是 braun.com.cncasetify.cnuniqlo.cnphilips.com.cn

原因很清楚:这些站会把访问者重定向到另一个国家的域名,而那个域名的注册域跟原域名不一样,于是被我自己的规则当成第三方拦掉了。被拦的是主文档本身,页面当然打不开——这跟第三方依赖毫无关系。

修法是给路由规则加一个前置判断:主文档请求及其重定向链一律放行。改完重跑,打不开的站从44个降到9个(6.9%)。

这类错误的可怕之处在于它给出的是一个“看起来很有新闻价值”的数字。33.6% 比6.9% 好看得多,而且完全说得通。凡是跑出一个特别符合预期的数字,先去看它的失败样本长什么样。类似的教训之前记过一次,那回是把噪声当成了差异,写在页面抖动基线与差异误报里。

正文基本还在

修正之后,109个可比对的站,掐断第三方后正文的保留比例:

正文保留比例站数占比
0.99以上4137.6%
0.90 ~ 0.992018.3%
0.50 ~ 0.902926.6%
0.05 ~ 0.501412.8%
0.05以下54.6%

中位数是0.946。也就是说,把所有外部依赖同时掐掉,一半以上的站正文只少了不到6%。25% 分位是0.711,10% 分位是0.208。

掉得最狠的几个:bigcommerce和bolia归零,uniqlo归零,sostrenegrene从31052掉到375,joolz从51756掉到5834,bugaboo从64784掉到13458。

另一头有48个站(44.0%)几乎不受影响,差异不到5%。这批站就是这次的对照组——它们证明拦截规则本身没有误伤第一方资源,否则所有站都该出现落差。给每次对比配一组本该没有差异的样本,这条在给建议配一个注定无效的对照组里单独讲过。

骨架一条不少

结构件那一组的结果更干脆:

  • 链接:掐断后保留比例中位0.986,完全归零的站只有4个。
  • 结构化数据:保留比例中位1.000,一个归零的都没有。
  • 页面主标题:保留比例中位1.000,只有1个站归零。

这三条负结果放在一起,指向同一个判断:一个页面能不能被机器读懂,跟它连着多少家第三方基本无关。那些外部依赖承担的是别的工作。

顺带一提,掐断之后有6个站的页面标题变了,其中glossier的标题直接变成空的。标题这种最基础的东西也可能挂在外部脚本上,而它一旦为空,社交分享和搜索结果里的呈现就全乱了。首页各处自我描述本来就常常对不上,那一层量在首页六份自我描述的实测里。

图片是唯一真塌的那一项

接下来是这次最刺眼的一个数。

掐断第三方之后,页面上真正加载出来的图片占比中位数只有0.055,25% 分位是0。换句话说,超过四分之一的站,一张图都出不来。

78.4% 的站有七成以上的图片加载失败。anker的109张图一张没出来,babybjorn的107张一张没出来,aboutyou的104张一张没出来。

原因不难理解:图片托管在图像处理与分发服务上,域名跟主站不同。这本身是合理的技术选择,性能上也是对的。但它意味着一个页面的视觉,几乎完全押在自己不控制的域名上——文字还在,版式还在,图全是空的。

这里要说清楚一个口径:如果只按注册域算,很多用了自定义域名(比如 img.example.com 指向外部服务)的站会被算成第一方,实际控制权仍在外面。所以这个78.4% 是下界,真实的依赖程度更高。

462个域,为什么两个站几乎不重合?

把127个站的第三方域全部合起来去重,得到462个不同的域。这个数字本身不奇怪,奇怪的是它们的分布。

三分之二只出现一次

出现范围域的个数占462的比例
只被1个站用到29563.9%
只被1到2个站用到36077.9%
被10个站以上用到265.6%
被30个站以上用到51.1%

被30个站以上用到的那5个是电商平台自己的域、它的支付入口、一家邮件营销服务和一个字体接口。除此之外,再没有任何一个第三方域出现在超过四分之一的站上。

0.051这个数

顺着这个分布做了一次两两比对:任取两个站,看它们的第三方域清单重合多少。用交集除以并集来算,127个站两两配对的平均重合度是0.051。

这个数说人话就是:你和隔壁那家同类电商,第三方依赖清单里能对上的部分,大约二十分之一。

这带来的实际后果是,有一整类工作没法靠行业经验代劳:

  • 别人整理的“常见第三方脚本清单”对你基本没用,因为你那份清单里三分之二的域不在任何一份公开清单上。
  • 按行业惯例配置的内容安全策略白名单,大概率会漏掉你自己那部分长尾。这一层配错了会静默拦掉资源,之前实测过一批支付页的策略配置,情况相当糟,记在支付页脚本策略实测里。
  • 供应商评估、数据处理协议这类合规工作,清单得自己盘,抄不来。

权威大样本为什么看不到这条长尾

这里有个有意思的对照。Web Almanac 2024年的第三方章节是这个领域样本量最大的公开分析,覆盖数百万个页面。但它在方法论里写明了一条筛选规则:只有在数据集里至少50个不同页面上出现过的域,才被计为第三方。

这条规则完全合理——它把偶发的、一次性的域挡在外面,让分类统计更稳。但它同时意味着:我这次发现的那295个只出现一次的域,在那套口径下根本不会被算进来。

两边不矛盾,量的是不同的东西。大样本量的是“生态里有哪些主要玩家”,小样本贴着单站量的是“你这一个站实际连着谁”。做自己站的盘点时,需要的是后者,而后者只能自己跑。

这些外部域,分别在干什么?

光知道个数没法行动,还得知道它们各自在干嘛。所以写了12条分类规则,覆盖标签管理、分析、广告、邮件营销、同意管理、客服、评价、电商平台、内容分发、字体、支付、风控这些常见类别,然后把128个站的第三方域逐个归类。

分类结果

用途用到它的站域次累计字节
归不了类108(84.4%)51269 MB
电商平台与插件72(56.3%)255727 MB
内容分发63(49.2%)104138 MB
邮件与短信营销54(42.2%)759 MB
字体与图标52(40.6%)815 MB
同意与隐私48(37.5%)675 MB
分析与监测47(36.7%)591 MB
评价与内容39(30.5%)467 MB
广告与再营销29(22.7%)50不足1 MB
在线客服22(17.2%)394 MB
风控与验证17(13.3%)17不足1 MB
支付与分期14(10.9%)15不足1 MB
标签管理14(10.9%)151 MB

单个站踩中的类别数,中位是4个,最多的一个站占了12类。

最大的那一类,是“归不了类”

这张表真正的内容在第一行。12条分类规则跑完,仍然有345个去重域归不了类,涉及84.4% 的站,而这345个里有252个只出现过一次。

这些域长什么样?出现最多的是社交平台的像素脚本(15个站)和一个A/B测试服务(9个站),再往下就全是4个站以下的:退换货服务、店内导购机器人、退货保险、归因分析、价格实验、前端加速代理、无障碍插件、愿望清单、功能开关平台、联盟推广。

这些名字多数人没听过,但它们各自是一个真实存在的公司,各自在页面上执行代码,各自能读到用户在页面上的行为。做一份分类表最大的收获,往往不是那些能归类的,而是发现归不了类的比能归类的还多。

字节和数量完全不是一回事

把字节那一列单独看一眼:电商平台与插件那一类727 MB,占绝对大头;内容分发138 MB;剩下十一类加起来不到100 MB。

而广告、风控、支付这三类,用到的站不少,累计字节都不足1 MB。它们的成本不在流量上,在别处——执行时间、隐私合规、以及页面对它们的可用性依赖。

按数量盘点会高估广告脚本、低估平台自带的东西;按字节盘点则正好反过来。两个维度都要看。这些外部资源具体拖慢了多少,可以用Lighthouse的第三方资源摘要按实体分组量一遍,它会把同一家公司的多个域合并计算耗时。

一半的字节,不是你发出去的

依赖数量之外,还有一笔字节账。

中位数39.1%,四分之三分位90.7%

按响应头声明的长度统计,第三方资源占页面全部字节的比例,中位数是39.1%。25% 分位8.2%,75% 分位90.7%——这个分布散得非常开。

有44.9% 的站,过半字节来自第三方。

这个数是保守的:没有声明长度的响应按0计。实际比例只会更高。

想给自己的数字找个参照系,HTTP Archive的Web现状报告有页面请求数与传输字节的长期趋势,能看出你这一档处在什么位置。不过要注意它统计的是全网抽样,电商站普遍高于中位水平。

累计字节最大的那个域,跟你想的不一样

把所有站的第三方字节按单个域累加(注意跟上面那张按类别汇总的表不是一回事),排第一的是电商平台自己的主域:67个站合计726 MB,2334次请求。这不意外。

意外的是第二名:一个图像优化服务,累计100 MB,但只有1个站在用。第四名是一家电商技术服务商,11 MB,也只有1个站在用。

这说明字节这件事上,“多少个站在用”和“吃掉多少流量”是两回事。一个只有你在用的第三方,完全可能是你页面上最大的那一块。盘点的时候按域名个数排序会漏掉它,得按字节排。

字节和抓取的关系

顺带说一层不太被提起的关系。抓取器对单个页面有取回上限,超了就截断,而截断是从后往前丢的。第三方资源虽然多数不计入主文档字节,但它们撑大的是整体加载负担和渲染时间,间接影响抓取那一侧愿意在这个页面上花多少资源。主文档自身的字节预算怎么算、超了会丢什么,之前单独量过一轮,见页面字节预算与抓取截断实测

那这些第三方,会不会真的挂?

前面造的是极端场景。现实里第三方到底稳不稳定,得单独看。

实测这一刻,基本都是活的

统计每个站的第三方请求里有多少返回了4xx或5xx:127个站里只有12个(9.4%)出现过,而且几乎都只是零星一两条。最多的一个站是90次请求里2次失败。

会返回错误的第三方域一共11个,最多的一个也只出现2次。

这是一条负结果,但很重要:第三方依赖的风险不在“它今天会不会挂”,而在别处。拿单次快照去论证可用性风险是站不住的。

真正的风险在三个别的地方

第一是慢,不是挂。掐断实验里那9个加载不完的站,问题不是资源返回错误,是等待。一个阻塞性的外部脚本响应慢,整个页面就卡在那儿。慢到什么程度会真的影响抓取那一侧,之前按服务器响应时间量过一轮,见服务器变慢与抓取速率

第二是变。第三方脚本的行为会自己改,不需要你更新任何代码。之前连续观测过两天半,就有四分之一的站上第三方脚本的默认行为发生了变化,记在第三方脚本默认值的静默漂移里。

第三是没了。域名过期、服务关停之后,页面上那条指向它的声明还在。之前扫过一批预连接声明,其中有几个指向的域名已经不存在了,细节在预连接指向的死域名实测里。

这份清单该由谁来盘?

数据说到这儿,剩下的是个组织问题。

每一个都是有人添的,加起来没人认领

把一个站的20多个第三方域拆开看,来路大同小异:建站时模板自带几个,市场部装了分析和广告的,客服团队装了在线咨询,运营装了评价和弹层,法务要求装了同意管理,前端为了性能引了个图像服务。

每一次添加都有明确的理由和明确的负责人,但没有任何一个环节负责这份清单的总量。而总量恰恰是决定页面表现的那个数。

盘点的正确姿势是按域,不是按脚本

常见的做法是列一份“我们用了哪些工具”的清单。这份清单通常是准的,但它不等于依赖清单,因为一个工具会拉进来好几个域。

正确做法是打开网络面板,按域名分组,把实际发生请求的域全列出来,逐个回答三个问题:这是谁、谁装的、去掉会怎样。有一批URL要批量提根域的话,站内有个域名提取器可以直接跑。

按这次的数据,你大概率会在这份清单上看到几个自己不认识的域。那几个就是标签管理器或者插件市场带进来的。

盘完之后,哪些该动哪些不必

先按三个维度排一遍

清单列出来之后别急着删。先给每个域标三样东西:它是不是阻塞主文档解析的、它吃掉多少字节、掐断它页面会不会塌。这三样对应三种完全不同的处理,混在一起看就没法排优先级。

发现什么怎么判断动作
没人认领的域问一圈没人知道直接去掉,观察一周
阻塞主文档解析的看它有没有async或defer改成异步,或延后加载
吃掉大量字节的按字节排序看前三换配置或换供应商
图片托管在外部掐断测试后图全空正常,但要有备用方案
只是数量多但都很小字节和阻塞都不显著不必动,记进清单就行

第二行那个动作是收益最确定的:把阻塞式引入改成异步或延后,页面不用等外部服务器就能先渲染出来。具体几种改法的适用场景与代价,web.dev关于第三方脚本加载优化的那篇列得比较全,照着对一遍就行。

把掐断测试做成常态检查

这次这个实验很容易接进流水线:给关键页面各跑一次“拦掉所有外部域”的加载,记三个数——正文保留比例、图片成功率、能不能在合理时间内加载完。

顺带说一句,这类脚本的行为不只会挂,还会被别的机制静默拦住——比如自己配的完整性校验哈希过期了,脚本下载完却一行都不执行,这个坑记在完整性校验与第三方脚本更新里。

三个数各自对应一类问题:正文掉了说明内容依赖外部服务,图片全空说明视觉依赖外部服务,加载不完说明存在阻塞性依赖。第三个是最该盯的,因为它在正常情况下完全隐形,只在对方慢的时候才发作。

顺便记得:主文档请求要放行,否则你测的是自己的规则,不是站点的依赖。这个坑本文前面栽过一次。

常见问题解答

第三方域多是不是就一定不好?

不一定。这次实测里第三方域数量与正文可读性、链接完整性、结构化数据都没有直接关系,掐断之后这三样基本不受影响。数量本身不是问题,问题在于有没有人知道这份清单、里面有没有阻塞性依赖、以及有没有没人认领的域。

为什么只读HTML看到的第三方那么少?

因为绝大多数第三方是脚本运行时拉进来的。一个标签管理器在HTML里只占一行,跑起来之后会按后台配置去请求十几个域。实测中位数是关掉脚本看到1个、脚本跑完看到8个,有26个站从最多2个涨到15个以上。

掐断第三方之后图片全没了,这算问题吗?

算正常现象,不算缺陷。把图片放在专门的分发服务上是对的技术选择。但它意味着页面的视觉完全依赖一个你不控制的域,所以需要两件事:一是知道这个依赖存在,二是想清楚对方长时间不可用时的表现,至少别让布局塌掉。

行业整理的第三方脚本清单能直接用吗?

参考可以,照搬不行。这次实测的462个第三方域里有295个只出现在一个站上,任取两个站的清单重合度平均只有0.051。公开清单覆盖的是那些高频出现的主流服务,而你的长尾部分只能自己盘。

那些大规模统计报告的数字,跟自己测出来的对不上怎么办?

先比口径再比数字。举个具体的:一份广为引用的大样本分析规定,只有在至少50个不同页面上出现过的域才算第三方,这条规则会把只出现一两次的长尾整个排除掉。两边量的东西不同,结论自然不同,不存在谁错。

第三方经常挂吗?

这次快照里不常挂,127个站里只有12个出现过第三方请求返回错误,而且都是零星一两条。但这不能证明可用性没有风险,因为单次快照测不出稳定性。实际更常见的风险是慢、是行为悄悄变了、是域名早就废弃但声明还留着。

用内容安全策略把第三方管起来,可行吗?

方向是对的,但要注意两件事。一是白名单必须基于自己站的实测清单,抄行业模板会漏掉长尾;二是配错了会静默拦掉资源,页面不报错但功能失效,所以上线前要用报告模式跑一段时间。

这次的数字能不能套到我的站上?

不能。样本是海外电商与品牌独立站,第三方使用强度明显高于内容型站点,也高于国内站点常见的技术栈组合。方法可以直接抄,数字要自己量。

权威参考资料

分享到
标签
版权声明

本文标题:《第三方脚本拉进8个域名,只看HTML一个都看不到》

本文链接:https://zhangwenbao.com/third-party-domain-dependency-invisible-in-html-audit.html

版权声明:本文原创,转载与引用请注明作者与原文链接。许可协议: CC BY 4.0

继续阅读
发表评论
分享到微信 或在下方手动填写
支持 Ctrl + Enter 提交