前端與HTTP那些事兒
各版本的http
發展
在HTTP建立之初,主要是為了傳輸超文字標記語言(HTML)文件。隨著時代的發展,也進行了若干次演進。下圖是各個版本釋出的時間軸。

image
目前為止,使用最為廣泛的是 http1.1 , http1.0 應該比較少了,最新的是 http2 。
這篇博文也主要,圍繞著1.0、1.1、2.0三個版本進行介紹。
http/1.0
http1.0不會複用tcp連結,每次請求都會開啟、斷開一條連結。
如果您看過我前陣子整理的 關於TCP的博文 ,您就會知道,TCP是有 延遲響應機制 的,每次請求並不會馬上返回。這算是http1.0效能不好的一個原因吧。

image
http/1.1
http/1.1當前普及程度最高的http版本。
到了http/1.1版本,tcp連結可以持久保持了(也就說,一段時間內,一個tcp連結會等到同一個域名下的所有資源載入完後再斷開。)

image
在保持tcp連結的基礎上,引入了 http管道 的機制,差點實現了 多路複用 。
http/1.1 without pipelining(不使用管道)
通過一條tcp連結請求資源,只有在上一個請求完成後,才能發出下一個請求。也就是上圖描述的情形。
http/1.1 with pipelining(使用管道)
客戶端不會等待響應,直接併發N個請求。但是,http/1.x有嚴格的 序列返回響應機制 。通俗的講就是: 請求時,不用等上一個完成;但響應時,必須嚴格按照順序返回 。
通過開發者工具,你就可以觀察到這一點。

image
基於以上描述,使用“ HTTP 管道”技術時,萬一第一個響應時間很長,那麼後面的響應處理完了也無法傳送,只能被快取起來,佔用伺服器記憶體,這就是傳說中的“ 隊首阻塞(head of line blocking) ”。
這也是http/1.x下,多數網路體驗不好的原因。
http/2.0
在介紹http/2.0之前,我們來先看一份 Akamai公司提供的一個官方演示 。
這裡用了361(19*19)張圖片,分別使用http/1.1,http/2.0兩種版本的協議進行對比。可以直觀的感受到,http/2.0比http/1.0快出5倍左右的速度。
考慮到您可能需要分別用開發者工具仔細檢視下兩個版本,我已經幫你找好了兩個版本對應的連結。(不客氣)
那http/2.0究竟引入了哪些機制、特性才達到目前的加速效果呢?簡答的說可以概括成。
-
二進位制分幀層
-
多路複用
-
首部壓縮
-
伺服器推送(server Push)
二進位制分幀層與多路複用
引入了 二進位制分幀層 ,就不再是文字傳輸了,而是資料幀(二進位制)。
注意:HTTP原本的語義,方法、動詞、首部都不受影響。僅僅是傳輸期間的資料格式變化了。

image
http/2規定了10種不同的幀。
如上圖,分針層會把 開始行 , 首部行 分割到 HEADERS幀 , 正文實體 分割到DATA幀。
TCP 連線在客戶端和伺服器間建立了一條運輸的通道,可以雙向通行,當一端要向另一端傳送訊息時,會先把這個訊息拆分成幾部分(幀),然後通過發起一個流對這些幀進行傳送,最後在另一端將同一個流的幀重新組合。
這裡涉及了以下概念。
流:已建立的連線上的雙向位元組流
訊息:與邏輯訊息對應的完整的一系列資料幀
幀:HTTP/2 通訊的最小單位,每個幀包含幀首部

image
其中幀對資料進行順序標識,這樣瀏覽器收到資料之後,就可以按照序列對資料進行合併,而不會出現合併後資料錯亂的情況。同樣是因為有了序列,伺服器就可以並行的傳輸資料,這就是流所做的事情。
HTTP/2對同一域名下所有請求都是基於流,也就是說同一域名不管訪問多少檔案,也只建立一路連線。同樣Apache的最大連線數為300,因為有了這個新特性,最大的併發就可以提升到300,比原來提升了6倍!
首部壓縮
在伺服器和客戶端各維護一個“首部表”,表中用索引代表首部名,或者首部鍵 - 值對,上一次傳送兩端都會記住已傳送過哪些首部,下一次傳送只需要傳輸差異的資料,相同的資料直接用索引表示即可。

image
首部壓縮,可以解決http頭臃腫的問題。
伺服器推送(server Push)
伺服器可以對一個客戶端請求傳送多個響應。也就是說,除了對最初請求的響應外,伺服器還可以額外向客戶端推送資源。
這裡就涉及到了另一個幀型別:PUSH_PROMISE幀。
舉個栗子,當客戶端請求index.html時,伺服器會同時推送style.css,index.js對應的PUSH_PROMISE幀。客戶端可以直接快取起來。
基於http/2對前端效能優化的思考
個人覺得前端的效能優化,應該主要從兩個方面。 載入速度 和 流暢執行 。
原引,在網上看到的一段話:
網頁不僅應該被快速載入,同時還應該流暢執行,比如快速響應的互動,如絲般順滑的動畫等。
http/1.x的優化方案
當然,今天的主題是討論網路協議,那我們只談載入速度。
基於http1.x的相關特性,可愛的前端們提出了很多頗具成效的優化方案。(精靈圖,多域名載入等等)其中,比較著名的 雅虎軍規 ,很多人應道都知道,這裡有一張整理好的圖。

image
http/2的變革
在http/2的基礎上,很多http/1.x要優化的問題,都不存在了。問題都不存在了,問題的優化方案也就不存在了。
這裡插一句,我始終堅信的一個觀點是: 沒有任何優化手段是不需要付出代價的。是藥三分毒,無非是取捨罷了。
1.合併css、js與精靈圖
在http/1.x時代,http並沒有最大程度上利用好tcp連結。雖然http/1.1裡有了 http管道 ,但其也帶來了 隊首阻塞 等問題,同時也要受佇列大小的限制。所以我們要通過合併檔案的方式減少http連結數量。
不錯,減少http請求數量的確能起到優化的作用,但與此同時,也有很多弊端:
-
所有檔案合成一個大檔案,那不管哪個模組發生變更,都要整體更新,使用者都要重新下載,無法繼續使用快取。
-
帶來了額外的維護成本。印象比較深的是維護精靈圖,稍微改一點,就得重新弄。
以上,就是” 合併css方案 "、“ 合併js方案 ”、“ 精靈圖方案 ”的優勢與弊端。
-
在http/1.x基礎上,明顯 優勢>弊端 ,所以我們使用這些方案。
-
但http/2,它對tcp連結的利用程度已經有了飛躍性的提升。此時這些方案是否 優勢>弊端 ,就值得商榷了。筆者覺得應該正好反過來。 優勢<弊端 。
2.分域名
在http/1.x基礎上,分域名有兩個好處。
- 為了繞過瀏覽器對同一域名的最大管道限制。可以同時請求更多內容。
- 同一域名下的請求報文,會匹配的站點的全部cookie,增大請求報文長度。而很多資源,比如圖片、css是不需要cookie的。
在http/2上,對於這些問題
- 原本就支援 多路複用 ,沒必要分
- 有 首部壓縮機制 ,首部行大點,也就傳一個。
3.介面合併
如果頁面需要多種資料,我們會盡量將資料彙總到一個介面,以減少http請求數量。
這種做法,幾乎違背了各種程式設計規範,比如“ 單一職責原則 ”等等,介面很難複用,維護成本高。
這種方案在http/2下,明顯弊端>優勢了。

最後,給大家推薦一個 前端學習進階內推交流群685910553 (前端資料分享),不管你在地球哪個方位,
不管你參加工作幾年都歡迎你的入駐!(群內會定期免費提供一些群主收藏的免費學習書籍資料以及整理好的面試題和答案文件!)
如果您對這個文章有任何異議,那麼請在文章評論處寫上你的評論。
如果您覺得這個文章有意思,那麼請分享並轉發,或者也可以關注一下表示您對我們文章的認可與鼓勵。
願大家都能在程式設計這條路,越走越遠。