HTTP/2 與 WEB 性能優(yōu)化(三)

2018-02-24 16:09 更新

在連續(xù)寫了兩篇關(guān)于「HTTP/2 與 WEB 性能優(yōu)化」的文章后,今天來寫這個(gè)系列的最后一篇。在正式開始之前,我們先來簡單回顧下之前兩篇文章:

HTTP/2 與 WEB 性能優(yōu)化(一)」的結(jié)論是:HTTP/2 的 Server Push 機(jī)制,可以讓重要的 JS、CSS 等資源盡快加載,從而不再需要 HTTP/1 中「將重要資源內(nèi)聯(lián)在頁面頭部」的優(yōu)化方案了。

HTTP/2 與 WEB 性能優(yōu)化(二)」的結(jié)論是:HTTP/2 支持了多路復(fù)用,HTTP 連接變得十分廉價(jià),之前為了節(jié)省連接數(shù)所采用的類似于「資源合并、資源內(nèi)聯(lián)」等優(yōu)化手段不再需要了。多路復(fù)用可以在一個(gè) TCP 連接上建立大量 HTTP 連接,也就不存在 HTTP 連接數(shù)限制了,HTTP/1 中常見的「靜態(tài)域名」優(yōu)化策略不但用不上了,還會(huì)帶來負(fù)面影響,需要去掉。另外,HTTP/2 的頭部壓縮功能也能大幅減少 HTTP 協(xié)議頭部帶來的開銷。

但 HTTP/2 并不是萬能的,并不是說用了 HTTP/2 就不再需要性能優(yōu)化了。我在本系統(tǒng)第二篇文章末尾寫到:

據(jù)官方預(yù)測,HTTP/1 至少還需要 10 年才能徹底退出歷史舞臺,另外盡管 HTTP/2 協(xié)議允許脫離 TSL 部署,但 Chrome 和 Firefox 都表示不支持非 TLS 的 HTTP/2,之后很可能一個(gè)網(wǎng)站會(huì)同時(shí)提供 HTTP/1.1、HTTP/1.1 over TLS、HTTP/2 over TLS 三種服務(wù)。如何在每種情況下,都能給用戶提供最好的體驗(yàn),需要更加深入的優(yōu)化研究和更加精細(xì)的優(yōu)化策略。

實(shí)際上,除了前兩篇文章中提到的這些需要為 HTTP/2 做出調(diào)整的優(yōu)化策略之外,其余大部分 HTTP/1 時(shí)期的優(yōu)化策略依然有效。HTTP/1 的 WPO 并不是什么新鮮話題,大家早就熟門熟路了,本文只打算列舉其中幾個(gè):

啟用壓縮

壓縮的目的是讓傳輸?shù)臄?shù)據(jù)變得更小。我們的線上代碼(JS、CSS 和 HTML)都會(huì)做壓縮,圖片也會(huì)做壓縮(PNGOUT、Pngcrush、JpegOptim、Gifsicle 等)。對于文本文件,在服務(wù)端發(fā)送響應(yīng)之前進(jìn)行 GZip 壓縮也很重要,通常壓縮后的文本大小會(huì)減小到原來的 1/4 - 1/3。對代碼進(jìn)行內(nèi)容壓縮已經(jīng)有成熟的工具和標(biāo)準(zhǔn)流程了,而服務(wù)端的 GZip 更是標(biāo)配,所以「壓縮」是一項(xiàng)收益投入比很高的優(yōu)化手段。

使用 HTTP 緩存

任何一個(gè) WEB 項(xiàng)目,要提高性能,各個(gè)環(huán)節(jié)的緩存必不可少。利用好 HTTP 協(xié)議的緩存機(jī)制,可以大幅減少傳輸數(shù)據(jù),減少請求,這又是一項(xiàng)收益投入比超高的優(yōu)化手段。這里把之前我寫的 HTTP/1.1 緩存機(jī)制介紹翻出來:

首先,服務(wù)端可以通過響應(yīng)頭里的?Last-Modified(最后修改時(shí)間) 或者?ETag(內(nèi)容特征) 標(biāo)記實(shí)體。瀏覽器會(huì)存下這些標(biāo)記,并在下次請求時(shí)帶上?If-Modified-Since: 上次 Last-Modified 的內(nèi)容?或?If-None-Match: 上次 ETag 的內(nèi)容,詢問服務(wù)端資源是否過期。如果服務(wù)端發(fā)現(xiàn)并沒有過期,直接返回一個(gè)狀態(tài)碼為 304、正文為空的響應(yīng),告知瀏覽器使用本地緩存;如果資源有更新,服務(wù)端返回狀態(tài)碼 200、新的 Last-Modified、Etag 和正文。這個(gè)過程被稱之為 HTTP 的協(xié)商緩存,通常也叫做弱緩存。

可以看到協(xié)商緩存并不會(huì)節(jié)省連接數(shù),但是在緩存生效時(shí),會(huì)大幅減小傳輸內(nèi)容(304 響應(yīng)沒有正文,一般只有幾百字節(jié))。另外為什么有兩個(gè)響應(yīng)頭都可以用來實(shí)現(xiàn)協(xié)商緩存呢?這是因?yàn)橐婚_始用的?Last-Modified?有兩個(gè)問題:1)只能精確到秒,1 秒內(nèi)的多次變化反映不出來;2)時(shí)間采用絕對值,如果服務(wù)端 / 客戶端時(shí)間不對都可能導(dǎo)致緩存失效。HTTP/1.1 并沒有規(guī)定?ETag?的生成規(guī)則,而一般實(shí)現(xiàn)者都是對資源內(nèi)容做摘要,能解決前面兩個(gè)問題。

另外一種緩存機(jī)制是服務(wù)端通過響應(yīng)頭告訴瀏覽器,在什么時(shí)間之前(Expires)或在多長時(shí)間之內(nèi)(Cache-Control: Max-age=xxx),不要再請求服務(wù)器了。這個(gè)機(jī)制我們通常稱之為 HTTP 的強(qiáng)緩存。

一旦資源命中強(qiáng)緩存規(guī)則后,再次訪問完全沒有 HTTP 請求(Chrome 開發(fā)者工具的 Network 面板依然會(huì)顯示請求,但是會(huì)注明 from cache;Firefox 的 firebug 也類似,會(huì)注明 BFCache),這會(huì)大幅提升性能。所以我們一般會(huì)對 CSS、JS、圖片等資源使用強(qiáng)緩存,而入口文件(HTML)一般使用協(xié)商緩存或不緩存,這樣可以通過修改入口文件中對強(qiáng)緩存資源的引入 URL 來達(dá)到即時(shí)更新的目的。

這里也解釋下為什么有了?Expire,還要有?Cache-Control。也有兩個(gè)原因:1)Cache-Control 功能更強(qiáng)大,對緩存的控制能力更強(qiáng);2)Cache-Control 采用的 max-age 是相對時(shí)間,不受服務(wù)端 / 客戶端時(shí)間不對的影響。

另外關(guān)于瀏覽器的刷新(F5 / cmd + r)和強(qiáng)刷(Ctrl + F5 / shift + cmd +r):普通刷新會(huì)使用協(xié)商緩存,忽略強(qiáng)緩存;強(qiáng)刷會(huì)忽略瀏覽器所有緩存(并且請求頭會(huì)攜帶 Cache-Control:no-cache 和 Pragma:no-cache,用來通知所有中間節(jié)點(diǎn)忽略緩存)。只有從地址欄或收藏夾輸入網(wǎng)址、點(diǎn)擊鏈接等情況下,瀏覽器才會(huì)使用強(qiáng)緩存。

減少 DNS 查詢

我們知道,建立 TCP 連接需要知道目標(biāo) IP,而絕大部分時(shí)候給瀏覽器的是域名。瀏覽器需要先將域名解析為 IP,這個(gè)過程就是 DNS 查詢,一般需要幾毫秒到幾百毫秒,移動(dòng)環(huán)境下會(huì)更慢。DNS 解析完成之前,請求會(huì)被 Block。瀏覽器一般都會(huì)緩存 DNS 查詢結(jié)果,頁面使用的域名(包括子域名)越少,花費(fèi)在 DNS 查詢上的開銷就越小。另外,合理使用瀏覽器的 DNS Prefetching 技術(shù),也是很好的做法。

減少重定向

無論是通過服務(wù)端響應(yīng)頭產(chǎn)生的重定向,還是通過?<meta>?或者 JS 產(chǎn)生的重定向,都可能引入新的 DNS 查詢、新的 TCP 連接以及新的 HTTP 請求,所以減少重定向也很重要。瀏覽器基本都會(huì)緩存通過?301 Moved Permanently?指定的跳轉(zhuǎn),所以對于永久性跳轉(zhuǎn),可以考慮使用狀態(tài)碼?301。對于啟用了 HTTPS 的網(wǎng)站,配置?HSTS?策略,也可以減少從 HTTP 到 HTTPS 的重定向。

WEB 性能優(yōu)化是一個(gè)系統(tǒng)工程,不可能在這一篇文章里寫完,我決定先就寫到這兒。最后,推薦一個(gè) Chrome 擴(kuò)展:HTTP/2 and SPDY indicator,它可以在地址欄顯示當(dāng)前網(wǎng)站是否啟用了 SPDY 或者 HTTP/2,點(diǎn)擊圖標(biāo)可以直接打開 Chrome 的 HTTP/2 的調(diào)試界面,十分方便。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號