为什么用了HTTP/2多路复用后图片加载反而更慢了?

a'ゞ嘉俊 阅读 22

我在优化网站时启用了HTTP/2,按理说多路复用应该更快,但发现首页轮播图的加载时间反而比HTTP/1.1多了200ms左右。检查网络面板发现,虽然所有图片都走同一个连接,但请求顺序好像被打乱了。

尝试过用fetch()设置优先级:


const controller = new AbortController();
controller.signal.addEventListener('abort', () => {
  console.log('Request canceled');
});
// 设置高优先级的fetch请求
fetch('/images/banner.jpg', {
  method: 'GET',
  headers: { 'Priority': 'u=1' }, // 这样设置对吗?
  signal: controller.signal
});

但浏览器开发者工具里没看到优先级生效的迹象。服务器是Nginx 1.20,配置了http2 on;,且测试工具显示确实支持HPACK压缩。难道HTTP/2的优先级需要服务端特殊配置?还是我的代码写法有问题?

我来解答 赞 6 收藏
二维码
手机扫码查看
1 条解答
闲人柯一
我之前也碰到过这问题,以为上了HTTP/2就万事大吉,结果关键资源反而被卡住。你那个 headers 里加 Priority: u=1 的方式其实是对的思路,但现实是:浏览器根本不完全支持你手动设优先级。

HTTP/2 的优先级机制确实存在,但它不是靠你在 fetch 里塞个 Priority 头就能生效的。这个优先级信息要通过 HTTP/2 协议层的“权重”和“依赖关系”来传递,而这些底层控制权不在客户端 JS 手上,浏览器会自己决定怎么排序请求,你的 headers 设置基本被忽略。

真正影响加载顺序的是浏览器的内部调度策略。比如你页面里的 img 标签,浏览器会根据渲染树自动提升它们的优先级,但如果你用 fetch 去拉图片再塞进 DOM,那它就被当成“低优先级资源”处理了——即使你写了高优先级头,fetch 默认还是走的是“脚本发起”的流程,不会提升到图片应有的等级。

解决办法有几个:

第一,别用 fetch 拉关键图片。轮播图这种视觉核心内容,直接用 ,让浏览器尽早发现并以高优先级加载。浏览器对原生 img 的优先级判断比我们手动写代码靠谱多了。

第二,如果非得用 JS 控制,可以用 preload 提示浏览器预加载:



或者在 JS 里动态创建 Image 对象:

const img = new Image();
img.src = '/images/banner.jpg'; // 浏览器会正确识别优先级

第三,服务端 Nginx 虽然开了 http2 on;,但默认不会做请求重排或优先级重写。你可以考虑配合使用 Link 头部做服务器推送(虽然现在用得少了),或者确保关键资源在 HTML 中尽早出现。

总结一下:HTTP/2 多路复用本身没错,慢是因为你把本该高优的资源用低优方式请求了。别迷信 fetch + 自定义头,浏览器对资源类型的原生语义才是优先级的关键。换成 img 或 preload,你会发现加载时机立马改善。
点赞 5
2026-02-08 23:02