从 HTTP/1.1 到 HTTP/2
HTTP/1.1 的瓶颈在于队头阻塞与连接浪费:一个 TCP 连接同一时间只能处理一个请求,浏览器靠并发连接硬扛,但连接数有限,页面资源一多就排队。HTTP/2 通过二进制分帧层解决这个问题:所有请求共用一个连接,以帧为单位交错传输,响应顺序不再被请求顺序卡住。
对开发者来说,HTTP/2 的升级大部分是透明的:协议协商靠 ALPN 自动完成,服务器配好 TLS 就行。但前端优化策略要跟着变:HTTP/1.1 时代把文件合并成一个、用雪碧图省请求数的做法,在 HTTP/2 下反而可能伤性能,多路复用让"少请求"不再重要,"按需加载"反而更优。
- 多路复用一个连接并发传多个请求响应。
- HPACK头部压缩降低重复传输。
- 优先级关键资源优先送达。
- Preload提前声明关键资源。
多路复用与头部压缩
多路复用把一个 TCP 连接切成多个逻辑流,每个流承载一个请求响应对,帧在流内有序、流间交错。服务器推送虽然也是 HTTP/2 特性,但容易浪费带宽,实际使用不多,预加载语义反而更受青睐。
头部压缩 HPACK 用静态表加动态表把重复的 Header 字段压缩:静态表预置常见字段,动态表缓存会话内高频字段,首帧全量传输后后续只传索引。Cookie 这类大头能省下大量字节,对弱网尤其友好。开启 HTTP/2 后,观察网络面板如果还有大量排队与重复头,多半是协议没真正生效或配置不对。
HTTP/2 实践配置
Nginx 开启 HTTP/2 只需在 listen 指令加 http2,前提是启用 TLS,因为主流浏览器只在 HTTPS 上协商 HTTP/2。配置完成后用开发者工具看协议版本,确认是 h2 而不是 http/1.1。
server {
listen 443 ssl http2;
server_name example.com;
ssl_protocols TLSv1.2 TLSv1.3;
# 连接复用与窗口优化
http2_max_concurrent_streams 128;
}
# 静态资源开启 gzip/brotli 压缩
gzip on;
gzip_types text/css application/javascript image/svg+xml;
HTTP/2 下要重新审视文件拆分:不再追求极致合并,而是让模块按需加载;CSS 与 JS 拆成小文件交给多路复用并行传。字体文件按字重分片,图片用响应式 srcset,让每个请求都物有所值。
QUIC 与 HTTP/3
HTTP/2 还有个遗留问题:队头阻塞在 TCP 层仍然存在,一个丢包会让整条连接的所有流都等待重传。QUIC 基于 UDP 实现可靠传输,每个流独立处理丢失,丢包只影响自己的流;还内置 TLS 1.3,握手从 2 个 RTT 降到 1 个,弱网下体验提升明显。
HTTP/3 就是跑在 QUIC 上的 HTTP。它默认启用连接迁移:手机从 Wi-Fi 切到移动网络,连接 ID 不变,不会断线重连。目前主流浏览器与 CDN 都已支持,站点配置主要靠 CDN 侧开启,自建服务器用支持 HTTP/3 的 Nginx 分支或 Caddy。升级 HTTP/3 不是替换 HTTP/2,而是让两者并存按浏览器能力协商。
资源预加载与优先级
页面性能的关键是让关键资源尽快到达。preload 提前声明"本次页面即将使用的关键资源"让浏览器尽早下载,prefetch 预取"将来可能用到的资源",preconnect 提前建立跨域连接,dns-prefetch 提前解析域名。
<link rel="preload" href="/css/app.css" as="style">
<link rel="preload" href="/fonts/icon.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preconnect" href="https://api.example.com" crossorigin>
<link rel="dns-prefetch" href="https://static.example.com">
预加载的正确用法是"救急不滥用":把影响首屏渲染的字体、CSS 里的关键图提前;把不需要的资源预加载反而是浪费带宽。结合资源优先级,浏览器会按优先级调度:关键渲染路径的资源标记 high,图片懒加载标记 low,让带宽花在刀刃上。
性能测量与回退
升级协议后要测量收益而不是想当然:用 Web Vitals 看 LCP 与 FCP 的变化,对比 HTTP/1.1 与 HTTP/2 下的资源加载时间瀑布图。协议协商失败会回退到 HTTP/1.1,性能暴跌,所以要监控协议分布:CDN 日志里统计 h2、h3、http/1.1 的比例,异常回退要告警。
- FCP首屏内容绘制时间。
- LCP最大内容绘制,核心体验指标。
- 协议比h2/h3 占比,监控异常回退。
# Performance API 获取协议信息
const entries = performance.getEntriesByType("resource");
entries.forEach(e => console.log(e.name, e.nextHopProtocol));
测量要放在真实网络环境:实验室数据与真实用户差距很大,用 RUM 采集真实用户的协议与加载时长,才能发现 CDN 边缘节点配置问题。
落地清单
HTTP/2 升级的落地顺序很明确:确认全站 HTTPS,开启 HTTP/2,验证协议生效;再评估资源拆分策略,把合并大文件改成按需小文件;给关键字体与首屏资源加 preload,第三方域加 preconnect;最后在 CDN 侧开启 HTTP/3 并持续监控协议分布。
协议升级的技术门槛不高,真正的工程在于优化策略的转变:从"减少请求数"转向"让每个请求更快更早"。配合预算制度,把关键资源体积与预加载策略写进构建流水线,性能才不会随功能迭代而退化。
- 全站 HTTPS 并开启 HTTP/2。
- 关键字体与首屏资源加 preload。
- 第三方域 preconnect,非关键资源懒加载。
- CDN 开 HTTP/3,监控协议分布回退。