按需加载 vs 汇总打包:实测对比

结论:请求数确实从 2 个变多到 5–25 个,这是唯一变差的指标;但实际传输字节少 23%–93%,插件 JS 执行量少一半以上,而且插件发版时只失效被改的那个文件,而不是让所有访客重下整包。

一、本机受控测试(25 个启用插件)

汇总方案(老做法):所有插件的 CSS 合成 1 个 279.5 KB(gzip 41.1 KB),JS 合成 1 个 217.1 KB(gzip 55.7 KB),共 2 个请求、484.9 KB 原始 / 95.5 KB gzip,每个页面全量加载。

按需实测(真实 HTTP 抓取,gzip 6 级):

页面实际加载(gzip)比汇总包省请求数
首页24.9 KB−74%10
版块39.5 KB−59%13
帖子15.6 KB−84%11
个人页9.7 KB−90%6
搜索 / 登录6.7 KB−93%5

登录页只需要 6.7 KB,却被塞 95.5 KB,93% 的流量和解析开销是浪费的。

会话内翻页(首页 → 版块 → 帖子 → 个人页 → 搜索 → 登录):共用资源已缓存,实际只请求 18 个文件、45.3 KB gzip;其中首页 10 个,版块新增 3 个,帖子新增 5 个,个人页/搜索/登录新增 0 个。

二、线上实测(bbs1.org)

环境已验证:HTTP/2 + nginx + cache-control: public, max-age=604800;全局 plugins.css / plugins.js 均为 0 字节(已完全按需)。

旧方案下的汇总包至少是跨页面并集:35 个文件、≥64 KB(gzip)。

页面按需实测旧方案(≥64 KB)
首页25 个请求,49 KB≥64 KB
版块18 个请求,29 KB≥64 KB
登录11 个请求,17 KB≥64 KB
搜索9 个请求,10 KB≥64 KB

搜索页省 ≥84%,登录页省 ≥72%,版块省 ≥54%。

三、请求数不是关键指标的两个理由

1. HTTP/2 多路复用

线上确认是 HTTP/2。同站点数十个静态请求复用一条连接,请求头经 HPACK 压缩;额外请求的成本是“一次 RTT 内并行完成”,不是逐请求串行等待。真正随量增长的是带宽、解析和 JS 执行。

2. 缓存粒度完全不同

线上资源带内容哈希且缓存 7 天,两种方案重复访问都是 0 请求。区别在失效粒度:

  • 汇总包的哈希是整包的:任何一个插件改动,所有访客的整包 URL 都变,≥64 KB(本机 95.5 KB)全部重新下载,哪怕他访问的页面用不到这个插件。
  • 按需模式只失效被改的文件:本机实测单文件 gzip 中位数 1.7 KB、平均 2.6 KB(user_level.css 3.0 KB,最重的 nb_editor.js 19.8 KB);线上典型文件 0.3–6.2 KB。
场景汇总方案重新下载按需方案重新下载
任一插件改动95.5 KB(本机)/ ≥64 KB(线上)中位 1.7 KB,典型 3–6 KB,最重 19.8 KB

一次发版的流量成本从整包降到约 1/20~1/40,对经常发版的插件市场是决定性差距。

四、还有两个汇总方案躲不开的成本

JS 执行:本机启用插件中 18 个带 JS。汇总方案每个页面都解析并执行全部 212 KB 脚本(18 个 IIFE,不少还注册了 MutationObserver);按需模式下:

页面汇总方案按需方案
首页18 个脚本 / 212 KB4 个 / 40.3 KB
版块18 个脚本 / 212 KB5 个 / 52.3 KB
搜索 / 登录18 个脚本 / 212 KB2 个 / 10.3 KB

首屏阻塞:CSS 在 <head> 里阻塞渲染。汇总方案阻塞 41.1 KB;按需模式下首页 14.3 KB、搜索页 3.2 KB。

五、边界条件

  • 冷启动:按需少 23%–93% 字节,请求多 3–23 个,HTTP/2 下可接受。
  • 热缓存:两者都是 0 请求;但按需是逐插件失效,汇总是一次改动全站失效。
  • 汇总方案唯一更优的场景:站点只启用两三个插件,或者还在 HTTP/1.1 且没开 keep-alive。本站是 28 个启用插件 + HTTP/2,不属于这种情况。
主楼