模块合并构建不是为http/2设计,因其天然支持多路复用,无同域名并发连接限制;它主要解决http/1.1下浏览器6连接/域名导致的队头阻塞问题。

“模块合并构建”本身不能规避 HTTP/2 的并发限制——因为 HTTP/2 本来就没有同域名的并发连接数限制,它只有单连接内流(stream)数量的限制(http2_max_concurrent_streams),而这个限制通常很高(默认128),且与文件数量无关。
真正需要打平小文件的场景,是针对 HTTP/1.1 环境下的浏览器并发连接限制(如 Chrome 的 6 连接/域名)。在 HTTP/1.1 中,每个资源(JS、CSS、图片等)都可能独占一个 TCP 连接或排队等待,大量小文件会加剧队头阻塞和连接争抢。此时,构建阶段合并模块(如将多个 JS 合并为 bundle.js)能显著减少请求数,从而绕过该瓶颈。
为什么不是为 HTTP/2 设计?
HTTP/2 天然支持多路复用:即使有 100 个小 JS 文件,只要走同一个域名+HTTPS+HTTP/2 连接,它们就共享一条 TCP 连接,按流并发传输,不触发“6 个连接”的限制。此时合并反而可能带来负面效果:
- 缓存失效粒度变大(改一个函数,整个 bundle 都要重下)
- 首屏加载变慢(非关键 JS 被提前加载)
- 破坏 HTTP/2 的流优先级和服务器推送能力
那什么时候该合并?看实际部署环境
如果你的服务仍需兼容 HTTP/1.1 客户端(如老旧企业内网、部分 IoT 设备、未升级的爬虫),或 CDN/边缘节点未启用 HTTP/2,则合并仍有价值。判断依据不是“是否用了 HTTP/2”,而是:
- 真实用户中 HTTP/1.1 流量占比是否 > 5%(可通过 CDN 或 Nginx access_log 的
$http_upgrade或$sent_http_alt_svc字段统计) - 静态资源平均体积是否
- 页面初始请求数是否持续 > 30(明显超出 6×5 域名分片的理论吞吐)
构建阶段自动打平的实用建议
不追求“全量合并”,而按加载时机和依赖关系智能聚类:
-
入口 chunk 合并:把
main.js+ 其直接依赖的 3–5 个核心工具模块(如 router、store)打包进一个文件,确保首屏逻辑一次加载到位 -
异步 chunk 拆分但预加载:对
import('./modal.js')类动态导入,保留单独文件,但用<link rel="preload" as="script">提前拉取,避免运行时卡顿 -
CSS 提取合并:所有组件级 CSS 提取到单个
styles.css,避免每个组件触发独立请求(HTTP/1.1 下尤其伤) -
使用现代打包器内置策略:Webpack 的
splitChunks.chunks: 'all'+minSize: 8192,Vite 的build.rollupOptions.output.manualChunks,可自动识别重复引用并聚类
真正的 HTTP/2 优化重点不在合并,而在利用其特性:启用 HPACK 头压缩、配置合理的 http2_max_concurrent_streams(如长连接多的 SSE 场景调低至 32)、开启 http2_push_preload 主动推送关键资源。










