今天聽👆哥說(吹)到他們網站用HTTP2推送接口請求極大的加快的網站訪問速度。其實我在去年研究 HTTP2_push 時就想到了這個情形。html
是否須要 push 靜態資源是有疑問的:因爲緩存的存在,你不能確保客戶端真的須要這個文件。雖然瀏覽器能夠主動阻止 PUSH 幀的發送,可是對於已發出的幀無能爲力。nginx
接口請求就不存在這個狀況:由於它們都不會被(被開發者禁掉了)瀏覽器緩存,每次打開頁面都須要從新加載。因此推送接口請求老是正確的選擇。git
Nginx 1.13.9 就增長了 HTTP2_Push 支持。Nginx 開啓 HTTP2 推送有兩種方法。github
強制推送某 URL。用法就是:json
http2_push URL;
這個 URL 能夠是反向代理的 API 請求地址。這樣推送的 HTTP2 幀能夠直接被瀏覽器使用。segmentfault
能夠看到,對於服務端推送的幀,瀏覽器會等到實際有請求時再去解析。api
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
能夠看到,對於服務端推送的幀,瀏覽器會在接收完畢後當即解析
至於哪一種狀況更好,各位讀者本身取捨。
示例中用到的代碼
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);
參考連接:
PS:http2_push_preload 的更高端用法多是使用 njs 或 openresty 動態添加 Link 頭實現動態推送資源(例如根據不一樣的用戶推送不一樣資源)
PS2:若是使用 Link 頭推送 API 資源,必定要添加 crossorigin
參數,不然瀏覽器不會使用收到的 PUSH 數據
PS3:經測試就算加了 crossorigin
頭 Chrome 也不必定會用收到的 PUSH 數據(而 Firefox 會,多是 bug),使用 http2_push
是最保險的方式