HTTP Client Hints 介紹

發表於2015-09-14

最近幾年各種 Web 技術一直在爆炸式發展,每天都有大量新東西湧現出來。針對這個現象,業內兩位大佬最近先後發文表達了自己的觀點:Stop pushing the web forwardIs the web platform getting too big?。其實很早之前我就意識到以我目前的精力,吃透所有 Web 新技術幾乎是不可能完成的任務,我關注新技術的側重點放在了效能優化上。

今天我要向大家介紹的技術是:HTTP Client Hints,也與效能優化有關。利用這項技術,HTTP 客戶端(通常可以認為是瀏覽器)能夠主動將一些特性告訴服務端,以便服務端更有針對性地輸出內容。這項技術由我們熟知的 Ilya Grigorik 提出,目前還處在較為早期的階段,較為正式的描述文件可以在這裡找到。目前 Chrome 46 (beta) 已支援它,IE 和 Firefox 則還在考慮中。

其實之前瀏覽器已經將很多自身特性放在 HTTP 請求中,例如下面這些頭部欄位:

  • User-Agent:提供瀏覽器型別及版本、作業系統及版本、瀏覽器核心等資訊;
  • Accept:表明瀏覽器支援哪些 MIME type(例如 Chrome 通過 Accept 表明自己支援 image/webp 圖片格式);
  • Accept-Encoding:表明本瀏覽器支援哪些內容編碼方式(例如:gzip、deflate、sdch);
  • Accept-Language:表明本瀏覽器支援那些語言;

通過以上這些頭部欄位,我們已經可以針對不同客戶端輸出不同內容。例如本部落格對支援 Webp 格式的瀏覽器會使用 Webp 來減少圖片大小;本部落格還會通過 User-Agent 針對 IE 老版本禁用 localStorage 快取策略。

但是有一些瀏覽器特性,我們無法直接獲取,如螢幕解析度、裝置畫素比(devicePixelRatio)、使用者頻寬等。而在移動 Web 中,為了儘可能節省使用者流量,需要輸出尺寸最合適的圖片資源。為了解決這個問題,常見的方案有:1)使用 JS 獲取這些特性,動態拼接圖片 URL;2)使用 HTML 中的 sizes 和 srcset 屬性、picture 標籤或 CSS 中的 image-set 屬性來實現響應式圖片。方案 1 很簡單,這裡略過;方案 2 網上有很多相關文章,不熟悉的同學可以自行搜尋「響應式圖片」瞭解下。

這裡看一個使用方案 2 中提到的 picture、sizes 和 srcset 實現的響應式圖片程式碼(via):

這段冗長的程式碼只是為了實現一張響應式圖片,儘管有一些誇張,實際使用時一般不會寫這麼全,但從中可以得到一個結論:在客戶端實現的策略越多,HTML 體積就越大越冗餘,可維護性和可讀性就越差。

而使用了 HTTP Client Hints 之後,瀏覽器在頁面發起子資源請求時,會通過新增的一系列頭部欄位帶上解析度、裝置畫素比、圖片寬度等資訊,使得各種複雜的策略可以挪到服務端去實現了。下面來看一看具體細節:

首先,有了支援 HTTP Client Hints 的瀏覽器之後,頁面上還需要顯式啟用它。這是因為不是所有服務端都實現了響應式輸出策略,每次都傳送這些新增的頭部可能會造成浪費。

與往常一樣,這個功能也可以通過 HTTP 響應頭和 meta 標籤兩種方式開啟並配置:

或:

在啟用了 HTTP Client Hints 的頁面中,所有子資源請求(無論什麼型別,無論什麼方式建立),都會攜帶 Accept-CH 屬性中所指明的頭部,例如:

有了這些頭部,圖片伺服器可以知道客戶端的 devicePixelRatio 是 2、圖片寬度是 128px、支援 Webp 格式,所以輸出 256px 的雙倍 Webp 圖最合適。但是瀏覽器怎麼知道這個圖片需要作為雙倍圖來使用呢(也就是說還是顯示為 128px)?這就需要在響應頭中增加下面這個欄位作為 DPR 的迴應:

需要注意的是,請求頭中的 Width 欄位,是根據 img 標籤上的 sizes 屬性算出來的。如果圖片沒有指定 sizes,或者圖片請求是通過 JS 建立的,瀏覽器無法得知 Width,也就不會攜帶這個頭部。

實際上,除了 DPR、Viewport-Width 和 Width 之外,文件還規定了兩個欄位,但是經過我的測試 Chrome 46 並沒有支援它們,這裡簡單介紹下:

  • Downlink:用來指示當前網路的下行鏈路頻寬,單位是 Mbps;
  • Save-Data:用來指示當前瀏覽器是否工作在省流模式之下,取值為 1 或 0;

可以看出這兩個屬性,也是為了儘可能給使用者節省頻寬而設計的。可以預見,後續還會有更多欄位加到 HTTP Client Hints 協議中來。隨著 HTTP/2 的普及,頭部壓縮使得增加幾個頭部欄位帶來的開銷變得很小了。

值得注意的是,使用了 HTTP Client Hints 之後,服務端針對同一個 URL 可能會輸出不同的內容,所以無論是中間節點,還是瀏覽器,在實現響應 Cache 時必須小心,需要針對不同的情況快取多份內容。這需要用到 HTTP/1 中的  Vary 響應頭,例如:

表明如果需要快取這個響應,在生成快取 Key 的時候需要將請求頭中的 DPR、Width 和 Downlink 的值計算進去。

好了,HTTP Client Hints 技術就介紹到這裡。很欣慰地看到,大部分 Web 新技術都是在給 HTML、CSS 和 JavaScript 增加功能和特性,而這項技術卻是把之前複雜的程式碼和邏輯往後移,讓我們的 HTML 程式碼能夠輕裝上陣。一些開源圖片處理系統已經開始支援這個新特性了,國外的一些 CDN 託管服務肯定也在蠢蠢欲動,我十分期待它的未來。

相關文章