HTTP/2推送之难,远超想象(2)

Edge的支持很贫瘠,但至少也是“一致的”贫瘠。因此你需要通过User-Agent嗅探的方式来确保只向Edge推送能被它使用的资源。如果因为任何原因做不到这一点,那么更稳妥的方法是避免向Edge用户推送任何内容。

Safari的表现有些缺乏必然性,但这个问题不是你能解决的。请使用User-Agent嗅探机制避免向Safari用户推送资源。

可以推送非缓存和非存储资源

为了使用HTTP缓存,项必须具备诸如max-age等属性,才能让浏览器无需与服务器重新验证而直接使用(这里有篇介绍缓存报头的文章)。HTTP/2推送则不同,并不需要检查匹配项的“新鲜度”。

Chrome - 良好支持

Safari - 良好支持

Firefox - 良好支持

Edge - 良好支持

所有浏览器都表现出了相同的行为。

建议

一些单页应用由于不仅需要使用JS,还需要在JS开始执行时获取其他数据(例如JSON之类的)才能顺利渲染,因此经常会遇到性能问题。此时最佳解决方案是服务器端渲染,但如果不可行,可以将JS与JSON和页面一起推送。

然而考虑到上文提到有关Edge/Safari的问题,更可靠的做法是使用内联式JSON。

HTTP/2推送缓存是浏览器需要考虑的最后一道缓存

推送项与HTTP/2共存,这意味着浏览器只会在之前的所有缓存(例如、预载缓存、服务工作进程,以及HTTP缓存)都没有提供时才会使用HTTP/2的推送项。

Chrome - 良好支持

Safari - 良好支持

Firefox - 良好支持

Edge - 良好支持

所有浏览器都表现出了相同的行为。

建议

有个问题需要注意。举例来说,如果在HTTP缓存中有一个匹配项,并且按照其max-age来看这个项还很新鲜,但随后又推送了一个更新鲜的项,推送的项将被忽略,浏览器会继续使用HTTP缓存中那个较老的项(除非API因为任何原因跳过了HTTP缓存)。

身处“缓存链”的最末尾似乎不是什么大问题,但了解到这种缓存项与连接的共存,这帮助我理解了以前观察到的很多其他行为。例如……

如果连接关闭,那就跟推送缓存道别吧

推送缓存会与HTTP/2连接共存,因此连接关闭后缓存也会丢失。就算所推送的资源有很大可能会被缓存,依然会发生这种情况。

推送缓存位于HTTP缓存之后,因此只有在浏览器请求后,项才会进入HTTP缓存。此时项才能从推送缓存,途径HTTP缓存、服务工作进程等到达页面。

如果用户的连接不稳定,此时虽然可能成功推送某些资源,但会在页面恰好得到这些资源之前丢失连接。这意味着需要新建连接并重新下载资源。

Chrome - 良好支持

Safari - 良好支持

Firefox - 良好支持

Edge - 良好支持

所有浏览器都表现出了相同的行为。

建议

不要过于依赖在推送缓存里长时间保存的项。推送这种方式最适合紧迫性高的资源,推送资源,以及该资源最终被使用,这两个阶段间隔的时间越短越好。

多个页面可使用同一个HTTP/2连接

每个连接都有自己的推送缓存,但多个页面可使用同一个连接,这意味着多个页面可能共享同一个推送缓存。

在实践中这意味着,如果在响应导航操作的过程中推送了资源(例如一个HTML页面),这个资源将不会是该页面专用的(下文将使用“页面”这个词,但实际上也可用于代表其他可以获取资源的东西,例如工作进程)。

Chrome - 良好支持

Safari - 糟糕支持

Firefox - 良好支持

Edge - 部分支持

Edge似乎会为每个标签页使用一个新连接(问题描述,含视频)。

Safari会不必要地为同一个源创建多个连接,我很确信这就是造成各种怪异问题的根源(问题描述,含视频)。

建议

在伴随页面推送诸如JSON数据等东西时需要注意这个问题,因为最终使用这些东西的可能并不是同一个页面。

这种行为有一定好处,例如伴随一个页面推送的资源可以被安装中服务工作进程发起的请求所使用。

Edge的行为虽然不是最优的,但目前还不需要担心。一旦Edge开始支持服务工作进程,这可能会成为一个问题。

再次提醒,我会避免向Safari用户推送资源。

不包含凭据的请求将使用单独的连接

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/90e04b79b9d458bc3a9d0955b0bda1c8.html