天天看點

HTTP網絡協定中的HTTP Client Hints 技術

最近幾年各種 web 技術一直在爆炸式發展,每天都有大量新東西湧現出來。針對這個現象,業内兩位大佬最近先後發文表達了自己的觀點:stop pushing the web forward、is 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 托管服務肯定也在蠢蠢欲動,我十分期待它的未來。

作者:何妍 

來源:51cto

繼續閱讀