在 HTTP/2 环境下慎用雪碧图(CSS Sprite),主要是因为 HTTP/2 的核心特性改变了网络请求的底层逻辑,使得传统雪碧图“减少请求数”的优势大幅降低,而其自身的缺点却被放大。具体原因如下:
1. 多路复用消除了“请求数”瓶颈
HTTP/1.1 时代使用雪碧图,主要是为了规避浏览器对同一域名的并发连接数限制(通常约 6 个),解决“队头阻塞”问题。而 HTTP/2 引入了多路复用(Multiplexing)技术,允许在单个 TCP 连接上无限制地并行发送多个请求。这意味着请求 100 张小图和请求 1 张大图的耗时几乎相同,合并请求带来的性能收益微乎其微。
2. 缓存颗粒度变粗,维护成本增加
雪碧图将所有小图标合并为一张大图,导致缓存粒度极粗。只要雪碧图中修改了哪怕 1 个像素的图标,整张大图的哈希值都会改变,导致浏览器必须重新下载整张图,使得其他未修改图标的缓存全部失效。而在 HTTP/2 下,保持小图标独立,浏览器可以对每个文件进行细粒度的强缓存管理,更新某一个图标不会影响其他图标。
3. 头部压缩降低了小请求的开销
HTTP/2 采用了 HPACK 算法对请求头进行压缩,相同或相似的 Header 只需要发送一次,后续请求通过索引引用。这极大降低了每次发起独立小图请求时的额外网络开销,使得单独请求小图不再像 HTTP/1.1 那样“昂贵”。
4. 增加了代码维护与定位的繁琐度
使用雪碧图需要开发者手动计算和编写复杂的 background-position 属性来精确定位显示区域,这增加了代码的维护成本。在 HTTP/2 环境下,这种繁琐的维护工作已经失去了对应的性能回报。
综上所述,在 HTTP/2 环境下,拆分资源反而更有利于发挥细粒度缓存和并行下载的优势。如果确实需要合并图标,目前更推荐的做法是使用 SVG Sprite(矢量雪碧图),它既支持无限缩放、完美适配高清屏,又能通过 currentColor 随主题变色,且 gzip 压缩后体积依然很小。