其实上面的说法有点不准确,因为在Fetch android.com时,需要执行DNS查询,最终会将developers.google.com指向一个不同的IP,因此需要新建连接并失去推送缓存中的项。
为了解决这个问题,可以使用ORIGIN frame,它可以让连接说:“嘿,如果你需要向android.com请求任何资源,问我要就行了,不需要搞DNS那些事”,只要developers.google.com是android.com的权威就行。这种特性非常适合一般的连接聚合(Connection coalescing),但还是一种新技术,目前仅Firefox Nightly支持。
如果使用了CDN或其他某种类型的共享主机,还需要检查一下证书,看看应该从哪个源开始为你的网站推送内容。这个过程比较麻烦,不过好在(据我所知)没有任何主机能针对HTTP/2推送提供全面的控制能力,而规范中的下列注解使得这一点几乎无法实现:
如果有多个租户共用同一台服务器,服务器必须确保租户无法推送并非以自己为权威的资源表征。
—
这样做很有必要。
Chrome - 良好支持
Safari - 部分支持
Firefox - 支持情况未知
Edge - 支持情况未知
Chrome 可以让网站推送以自己为权威的其他源的资源。如果其他源解析为相同IP地址,则可以继续使用原有的连接,因此已推送的项可以直接使用。Chrome目前尚不支持ORIGIN frame。
Safari可以让网站推送以自己为权威的其他源的资源,但需要为其他源新建一个连接,因此推送的项其实永远不会被使用。Safar不支持ORIGIN frame。
Firefox会拒绝其他源的推送。与Safari类似,会为其他源新建连接,然而我在Firefox中跳过了有关证书的警告,因此结果可能不可靠。Firefox Nightly可支持ORIGIN frame。
Edge也会拒绝其他源的推送。同样因为跳过了证书警告,因此在证书没问题的时候结果可能有所差异。Edge不支持ORIGIN frame。
建议如果在同一个页面上使用了多个源,但最终会指向同一台服务器,则可以考虑使用ORIGIN frame。一旦该技术得到广泛支持,将不再需要进行DNS查询,可改善性能。
如果你觉得跨源推送的好处更大,建议写几个比本文更好的测试,确保浏览器可以真正使用你所推送的内容。否则可以通过User-Agent嗅探机制推送给不同浏览器。
推送还是预载除了推送资源,我们还可以使用HTML让浏览器预载资源:
<link href="https://fonts.example.com/font.woff2" as="font" crossorigin type="font/woff2" >或者使用页面头:
Link: <https://fonts.example.com/font.woff2>; rel=preload; as=font; crossorigin; type='font/woff2'href – 要预载的URL。
as – 响应的,这意味着浏览器可设置恰当的报头并应用相应的CSP策略。
crossorigin – 可选,代表这是一个CORS请求。CORS请求可在不含凭据的情况下发送,除非使用了crossorigin="use-credentials"。
type – 可选,如果所提供的MIME类型不被支持,可以让浏览器忽略预载。
浏览器看到预载链接后,将会进行Fetch。该功能类似于HTTP/2推送,但:
一切均可预载。
no-cache和no-store项也可以预载。
只有凭据模式相同的情况下,请求才能与预载项相匹配。
缓存的项只能使用一次,不过可以放在HTTP缓存中以备随后Fetch。
除了新鲜度,还可以通过HTTP语义进行项的匹配。
可以预载来自其他源的项。
此外还有下列不同之处:
浏览器会Fetch资源,这意味着浏览器会按顺序从服务工作进程、HTTP缓存、HTTP/2缓存,以及目标服务器中获取响应。
预载的资源将独立于页面(或工作进程)存储。这意味着预载资源将会是浏览器首先检查的缓存(先于服务工作进程和HTTP缓存),连接丢失不会导致预载项丢失。与页面之间的直接链接也意味着如果预载项未使用,将能通过开发工具看到包含有用提示的警告信息。