HTTP/2多路复用由TLS握手时ALPN协商自动启用,无需HTML开启;关键在于统一主域名避免子域名分片、用preload提前触发关键资源请求并设as属性、禁用同步脚本阻塞、验证Protocol为h2且同域名请求共享Connection ID。

HTTP/2 多路复用本身不需要“开启”,它由服务器和浏览器在 TLS 握手时通过 ALPN 协商自动启用。真正影响排队是否被消除的,不是协议有没有开,而是 HTML 写法和资源组织方式有没有让多路复用真正生效。
关键在于:多路复用要起作用,必须让多个请求走同一个 TCP 连接、共享同一个流上下文。一旦资源分散到不同域名,连接就拆开了,复用就断了——排队问题自然卷土重来。
统一主域名,停用子域名分片
HTTP/1.1 时代为绕过 6~8 个连接限制,常用 static1.example.com、cdn.example.com 等多个子域名。但在 HTTP/2 下,这种做法反而有害:
- 每个子域名需独立完成 DNS 查询、TCP 握手、TLS 握手、SETTINGS 帧协商,增加 RTT 延迟
- 浏览器无法跨域名复用连接,main.js 和 logo.png 分属两个连接,流 ID 不互通,优先级调度失效
- CDN 或证书配置稍有差异,连接可能被强制中断重连
✅ 正确做法:所有静态资源(CSS、JS、图片、字体)全部使用同一主域名,例如https://example.com/assets/app.jshttps://example.com/images/logo.svg
不加前缀、不拆二级域、不引入额外 host。
用 preload 提前触发关键请求,填满复用通道
HTML 解析是线性的,遇到 <script src="app.js"> 才发起请求,中间几十毫秒连接空闲。而 <link rel="preload"> 可在解析早期就抢占流通道:
- 必须带
as属性,否则浏览器无法设置正确 MIME 类型和缓存策略<link rel="preload" href="/styles.css" as="style"><link rel="preload" href="/hero.webp" as="image" fetchpriority="high"> - 只预加载首屏必需资源(LCP 图片、关键 CSS、核心 JS)
- 非关键资源(统计脚本、页脚广告)不要 preload,会挤占带宽
注意:preload 不执行代码,只是提前下载;后续仍需 <script> 或 <link rel="stylesheet"> 显式引入。
避免同步脚本阻塞 HTML 解析流
即使连接已建立、多路复用就绪,一个没加 async 或 defer 的外部 <script> 仍会暂停 HTML 解析,导致后续 <img>、<link> 标签无法及时生成请求——复用连接空转,资源加载被迫串行。
- 对非首屏依赖的 JS,优先用
async(无顺序要求)或defer(按文档顺序执行) - 若必须同步执行(如某些初始化逻辑),考虑将强依赖打包进同一文件,减少请求数量
- 切记:多路复用解决的是传输层队头阻塞,不是 JS 执行阻塞;
document.write()或未声明模块依赖仍会报错
验证是否真正在用多路复用
别只看瀑布图里“pending”状态——那是 DevTools 的 UI 抽象,并不代表连接没复用。
真实验证方法:
- 打开 Chrome DevTools → Network 面板
- 刷新页面,选中任意一个请求 → 查看 Headers 标签页 → 确认 Protocol: h2
- 再查看该请求的 Connection ID 字段,对比其他同域名请求,ID 应完全一致
- 同时检查 Initiator 列,多个资源应显示为
Parser或Preload Scanner,而非被某个 script 卡住
只要 Protocol 是 h2、Connection ID 相同、关键资源无长串 blocking 阶段,说明多路复用已在工作,传统 HTTP/1.1 式排队基本消失。


















