關於 http2 下 push 接口請求的正確姿式

今天聽👆哥說(吹)到他們網站用HTTP2推送接口請求極大的加快的網站訪問速度。其實我在去年研究 HTTP2_push 時就想到了這個情形。html

是否須要 push 靜態資源是有疑問的:因爲緩存的存在,你不能確保客戶端真的須要這個文件。雖然瀏覽器能夠主動阻止 PUSH 幀的發送,可是對於已發出的幀無能爲力nginx

接口請求就不存在這個狀況:由於它們都不會被(被開發者禁掉了)瀏覽器緩存,每次打開頁面都須要從新加載。因此推送接口請求老是正確的選擇。git

Nginx 1.13.9 就增長了 HTTP2_Push 支持。Nginx 開啓 HTTP2 推送有兩種方法。github

http2_push 指令

強制推送某 URL。用法就是:json

http2_push URL;

這個 URL 能夠是反向代理的 API 請求地址。這樣推送的 HTTP2 幀能夠直接被瀏覽器使用。segmentfault

clipboard.png

能夠看到,對於服務端推送的幀,瀏覽器會等到實際有請求時再去解析。api

http2_push_preload 指令

Nginx 會解析預加載 Link 頭動態的推送某 URL。用法爲:瀏覽器

http2_push_preload on;
add_header Link "<URL>; rel=preload; as=TYPE; [crossorigin]";

URL 同上可爲反代的 API 請求地址,但此時 TYPE 應爲 fetch,而且添加 crossorigin 參數。例如:緩存

add_header Link "</restapi/shopping/v1/cities>; rel=preload; as=fetch; crossorigin";

這樣的話,Nginx 一樣會推送這個 API 資源。不一樣的是,瀏覽器因爲收到了 preload_link 頭,同時會預加載這個資源。post

clipboard.png

能夠看到,對於服務端推送的幀,瀏覽器會在接收完畢後當即解析

至於哪一種狀況更好,各位讀者本身取捨。

示例中用到的代碼

setTimeout(() => {
  const xhr = new XMLHttpRequest();
  xhr.responseType = 'json';
  xhr.onload = e => {
    console.log(xhr.response);
    document.querySelector('pre').textContent = JSON.stringify(xhr.response, null, 2);
  };
  xhr.open('GET', '/restapi/shopping/v1/cities');
  xhr.send();
}, 1000);

參考連接:

  1. https://bugs.chromium.org/p/c...
  2. https://developer.mozilla.org...
  3. https://w3c.github.io/preload/
  4. https://jakearchibald.com/201...

PS:http2_push_preload 的更高端用法多是使用 njsopenresty 動態添加 Link 頭實現動態推送資源(例如根據不一樣的用戶推送不一樣資源)
PS2:若是使用 Link 頭推送 API 資源,必定要添加 crossorigin 參數,不然瀏覽器不會使用收到的 PUSH 數據
PS3:經測試就算加了 crossorigin 頭 Chrome 也不必定會用收到的 PUSH 數據(而 Firefox 會,多是 bug),使用 http2_push 是最保險的方式

相關文章
相關標籤/搜索