從輸入cnblogs.com到博客園首頁完全展示發生了什麼

来源:http://www.cnblogs.com/iovec/archive/2017/11/28/7904416.html
-Advertisement-
Play Games

之前面試時候經常被問及從輸入一個網址到頁面完全展示出來都發生了什麼,支支吾吾回答沒有底氣,仔細研究了一下,發現裡面學問還真不少。這些被瀏覽器封裝起來的東西,瞭解之後才對前端的一些流行做法恍然大悟。 ...


之前面試時候經常被問及這個問題,支支吾吾回答沒有底氣,仔細研究了一下,發現裡面學問還真不少。

從輸入 cnblogs.com 到博客園首頁完全展現這個過程可以大致分為網路通信頁面渲染兩個步驟。

網路通信

  1. DNS 解析成 IP 地址
  2. 發送 http 請求
  3. TCP 傳輸報文
  4. IP 定址
  5. 封裝成幀
  6. 物理傳輸

頁面渲染

網路通信走的五層網際網路協議棧(OSI標準是七層模型,但實際實現通常是五層)。畫了一張圖:

五層網際網路協議棧

應用層

1. DNS 解析成 IP 地址

DNS屬於應用層協議。客戶端會先檢查本地是否有對應的 ip 地址,如果有就返回,否則就會請求上級 DNS 伺服器,知道找到或到根節點。這一過程可能會非常耗時,使用 dns-prefetch 可使瀏覽器在空閑時提前將這些功能變數名稱轉化為 ip 地址,真正請求資源時就避免了這個過程的時間。例如京東首頁的處理:

京東首頁dns-prefetch處理

2. 發送 http 請求

HTTP也是應用層協議。HTTP(HyperText Transport Protocol)定義了一個基於請求/響應模式的、無狀態的、應用層的協議,用於從萬維網伺服器傳輸超文本到本地瀏覽器。絕大多數的Web開發,都是構建在HTTP協議之上的Web應用。客戶端組織併發送 http 請求報文,包含 method、url、host、cookie 等信息,下麵是訪問博客園首頁時 http 請求報文的樣子:

GET https://www.cnblogs.com/ HTTP/1.1
Host: www.cnblogs.com
Connection: keep-alive
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36
Upgrade-Insecure-Requests: 1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: __gads=ID=b62b1e22b7de2e02:T=1493954370:S=ALNI_MYRebVRavER2PJmwdeFwpl33ACNoQ;
If-Modified-Since: Mon, 27 Nov 2017 12:21:04 GMT

請求頭裡的每個欄位都有各自的作用,具體含義可查閱http協議相關文章。

傳輸層

3. TCP 傳輸報文

TCP 將 http 長報文劃分為短報文,通過“三次握手”與伺服器建立連接,進行可靠傳輸。“三次握手”建立連接的過程和打電話極像:

客戶端:喂,我要和 Server 通話

服務端:你好,我是 Server,你是 Client 嗎

客戶端:沒錯,我是 Client

連接建立成功,接下來就可以正式傳送數據了。

數據傳完之後斷開tcp連接還要通過“四次揮手”,大概意思如下:

客戶端:Server 小寶貝,我話說完了,你掛電話吧

服務端:我不掛,我不掛,你先掛,你不掛我也不掛

---------------- Client 一陣無語 --------------

服務端:你掛了嗎

客戶端:行,那我先掛了

至此完成了一次完整的資源請求響應。

需要註意的是,瀏覽器對同一功能變數名稱下併發的tcp連接數是有限制的,2個到10個不等。為瞭解決這個資源載入瓶頸,有幾種流行的優化方案:

  • 資源打包,合併請求

比如頁面樣式全部打包在一個 css 文件內,頁面邏輯全部打包在一個 js 文件內,圖片拼合成雪碧圖,這樣可有效減少頁面的資源請求數量。webpack 是時下最流行的模塊打包工具之一,它可以將頁面內所有資源(包括js,css,圖片,字體等等)都打包進一個 js 文件,不明覺厲。

  • 功能變數名稱拆分,資源分散存儲

當瀏覽器向伺服器請求一個靜態資源時,會先發送該功能變數名稱下的 cookies,伺服器對於這些 cookie 根本不會做任何處理,因此它們只是在毫無意義的消耗帶寬,所以應該確保對於靜態內容的請求是無 cookie 的請求(也就是所謂的 cookie-free)。將站點的 js、css、圖片等靜態文件放在一個專門的功能變數名稱下訪問,由於該功能變數名稱與主站功能變數名稱不同,所以瀏覽器就不會把主功能變數名稱下的 cookies 傳給該域,從而減少網路開銷,特別是細碎靜態文件特別多的情況下效果顯著。
另一方面,由於瀏覽器是基於功能變數名稱的併發連接數限制,而不是頁面。因此將資源部署在不同的功能變數名稱下可以使頁面的總併發連接數得到線性提升。

  • Connection: keep-alive,復用已建立的連接

在 http 早期,每個 http 請求都要打開一個 tcp 連接,請求完就關閉這個連接,導致每個請求都要來一遍“三次握手”和“四次揮手”,從而磨磨唧唧多出來大量無謂的等待時間。就好比出去吃飯,等飯等半個小時,端上來十分鐘吃完了,結賬排隊又等了半個小時,要是剛進來就吃現成的吃完就跑那多爽啊。keep-alive 乾的就是這件事,當第一個請求數據傳輸完畢之後,伺服器說“客戶端你不要關閉這個連接,直接換下個請求,我不想再握你的破手了”。這樣下個請求就直接傳輸數據而不用先走“三次握手”的流程了。這好比你又去吃飯,吃你最喜歡的紅燒肉,飯店在今天第一個客人點紅燒肉的時候就炒了一大鍋紅燒肉,你點餐的時候直接吃現成的就行了,吃完直接跑,哈哈美滋滋。

  • 控制緩存

將靜態資源強制緩存在客戶端,通過添加文件指紋等方式使客戶端只請求發生了變更的資源,可有效降低靜態資源請求數量。具體可參看前端靜態資源緩存控制策略

  • 延遲載入,懶載入,按需載入

很多頁面瀏覽量雖然很大,但其實很大比例用戶掃完第一屏就直接跳走了,第一屏以下的內容用戶根本就不感興趣。 對於超大流量的網站,這個問題尤其重要。這時可根據用戶的行為進行按需載入,用戶用到了就去載入,用不到就不去載入。

以上都是從減少建立tcp連接數量的角度去優化頁面性能,之後會分享更多前端性能優化方面的實用方法。

網路層

4. IP 定址

Internet Protocol 是定義網路之間彼此互聯規則的協議,主要解決邏輯定址和網路通用數據傳輸格式兩個問題。

所有連接到網際網路上的設備都會被分配一個唯一的 IP 地址,就像網購時填寫的收貨地址一樣。由於一個網路設備的 IP 地址可以更換,但是 MAC 硬體地址(就像身份證號)一般是固定不變的,所以首先使用 ARP 協議來找到目標主機的 MAC 硬體地址。當通信的雙方不在同一個區域網時,需要多次中轉(路由器)才能找到最終的目標,在中轉的過程中還需要通過下一個中轉站的 MAC 地址來搜索下一個中轉目標。

傳輸層傳來的 TCP 報文會在這一層被 IP 封裝成網路通用傳輸格式——IP數據包,IP 數據包是真正在網路間進行傳輸的數據基本單元。

通過邏輯定址定位到前面應用層 DNS 解析出來的 IP 地址的主機網路位置,然後把數據以 IP 數據包的格式發送到那去。

數據鏈路層

5. 封裝成幀

數據鏈路層負責將 IP 數據包封裝成適合在物理網路上傳輸的幀格式並傳輸。設計數據鏈路層的主要目的就是在原始的、有差錯的物理傳輸線路的基礎上,採取差錯檢測、差錯控制與流量控制等方法,將有差錯的物理線路改進成邏輯上無差錯的數據鏈路,向網路層提供高質量的服務。當採用復用技術時,一條物理鏈路上可以有多條數據鏈路。

物理層

6. 物理傳輸

上面這麼多層其實都是在為不同的目的對要傳輸的數據進行封裝處理,而物理層則是通過各種傳輸介質(雙絞線,電磁波,光纖等)以信號的形式將上面各層封裝好的數據物理傳送過去。

至此一個 http 請求漂洋過海終於到達了伺服器,接下來就是從物理層到應用層向上傳遞,將封裝的數據一層層剝開,伺服器在應用層拿到最原始的請求信息後快速處理完,然後就開始向客戶端發送響應信息。這次是以伺服器為起點,客戶端為終點再走一遍五層協議棧。

伺服器的響應消息跋山涉水終於到達了瀏覽器,接下來就是頁面渲染(更具體可參看瀏覽器內部工作原理)。


頁面的渲染工作主要由瀏覽器的渲染引擎來完成(這裡以Chrome為例)。

頁面渲染主流程

下麵是渲染引擎在取得內容後的基本流程:

解析html構建dom樹 -> 解析css構建render樹 -> 佈局render樹 -> 繪製render樹

渲染引擎首先開始解析html,並將標簽轉化為dom樹中的dom節點。接著,它解析外部css文件及style標簽中的樣式信息,這些樣式信息以及html標簽中的可見性指令將被用來構建另一棵樹——render樹。render樹構建好了之後,將會執行佈局過程,該過程將確定render樹每個節點在屏幕上的確切坐標。最後是繪製render樹,即遍歷render樹的每個節點並將它們繪製到屏幕上。

偷了一張圖片(Chrome和Safari所用內核webkit頁面渲染主流程):


webkit頁面渲染主流程

為了更好的用戶體驗,渲染引擎將會儘可能早地將內容繪製在屏幕上,而不會等到所有的html都解析完成後再去構建、佈局和繪製render樹,它是解析完一部分內容就繪製一部分內容,同時可能還在通過網路下載其餘內容(圖片,腳本,樣式表等)。比如說,瀏覽器在代碼中發現一個 img 標簽引用了一張圖片,於是就向伺服器發出圖片請求,此時瀏覽器不會等到圖片下載完,而是會繼續解析渲染後面的代碼,等到伺服器返回圖片文件,由於圖片占用了一定面積,影響了後面段落的佈局,瀏覽器就會回過頭來重新渲染這部分代碼。

dom樹和render樹的關係

render樹節點和dom樹節點相對應,但這種對應關係不是一對一的,不可見的dom元素不會被插入render樹,例如head元素、script元素等。另外,display屬性為none的元素也不會在渲染樹中出現(visibility屬性為hidden的元素將出現在渲染樹中,這是因為visibility屬性為hidden的元素雖然不可見但保留了元素的占位)。

又偷了一張圖:


render樹與dom樹

佈局render樹(layout)

當渲染對象被創建並添加到render樹後,它們並沒有位置和大小,計算這些值的過程稱為layout(佈局)。

佈局的坐標系統相對於根渲染對象(它對應文檔的html標簽,可用document.documentElement拿到),使用top和left坐標。根渲染對象的位置是 (0,0),它的大小是viewport即瀏覽器視窗的可見部分。佈局是一個遞歸的過程,由根渲染對象開始,然後遞歸地通過一些或所有的層級節點,為每個需要幾何信息的渲染對象進行計算。

為了不因為每個小變化都全部重新佈局,瀏覽器使用一個 dirty bit(頁面重寫標誌位)系統,一個渲染對象發生了變化或是被添加了,就標記它及它的children為dirty——需要layout。

當layout在整棵渲染樹觸發時,稱為全局layout,這可能在下麵這些情況下發生:

  1. 一個全局的樣式改變影響所有的渲染對象,比如字型大小的改變。
  2. 視窗resize。

layout也可以是增量的,這樣只有標誌為dirty的渲染對象會重新佈局(也將導致一些額外的佈局)。增量layout會在渲染對象dirty時非同步觸發,例如,當網路接收到新的內容並添加到dom樹後,新的渲染對象會添加到render樹中。

繪製(paint)

繪製階段,遍歷render樹並調用渲染對象的paint方法將它們的內容顯示在屏幕上。和佈局一樣,繪製也可以是全局的(繪製完整的樹)或增量的。在增量的繪製過程中,一些渲染對象以不影響整棵樹的方式改變,改變的渲染對象使其在屏幕上的矩形區域失效(invalidate),這將導致操作系統將其看作dirty區域,並產生一個paint事件,操作系統很巧妙的處理這個過程,並將多個區域合併為一個。

瀏覽器總是試著以最小的動作響應一個變化,所以一個元素顏色的變化將只導致該元素的重繪,元素位置的變化將導致元
素的佈局和重繪,添加一個dom節點,也會導致這個元素的佈局和重繪。一些主要的變化,比如增加html元素的字型大小,將會導致緩存失效,從而引起整個render樹的佈局和重繪。

等到繪製完畢,頁面就完全地展現在我們面前了。

看似再簡單不過的操作,背後支撐的技術鏈已經複雜到不可想象。上面只是粗淺的輪廓,其中的每一步深挖進去都是一門大學問。不過咱們前端瞭解一下就行了,沒必要較這個勁,不然就捨本逐末了。

覺得有用就點個推薦吧,來波關註就更好了:)


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.下載Maven版本 官網地址:http://maven.apache.org/download.cgi 直接下載Maven網址:https://mirrors.tuna.tsinghua.edu.cn/apache//maven/ 尾碼為tar.gz的可用於Linux系統上,尾碼為zip可直接用 ...
  • Elasticsearch版本:6.0一、ES的集群 由一個或多個相同cluster.name的節點組成,共同承擔數據和負載的壓力。 被選舉的主節點將負責管理集群範圍內的所有變更,如增加/刪除索引、增加/刪除節點等,但是不涉及文檔級別變更和搜索等操作。 請求可以發送到集群中的任何節點上,每個節點都知... ...
  • 錯誤原因是,字元串以 \ 結尾 或者字元串缺少引號。 寫代碼拼接windows 路徑出現這個錯誤, 查資料才知道 python中字元串不能以 \ 結尾 我的代碼如下 運行則報錯 那麼如何解決呢 方法一 : 使用 os.path.join 方法二:路徑的反斜杠使用轉義 而不用 r 為何 字元串不能 以 ...
  • Elasticsearch版本:6.0一、文檔一個文檔不僅包含數據,也包含元數據,三個必須的元數據如下_index:具有共同特性分到一起的文檔集合,標示了文檔的存放位置; 名字小寫,不以下劃線開頭,不包含逗號。_type:表示文檔的類型,在索引中對數據進行邏輯分區; 名字大寫或小寫,不以下劃線或句號... ...
  • 本文介紹了Kafka Stream的背景,如Kafka Stream是什麼,什麼是流式計算,以及為什麼要有Kafka Stream。接著介紹了Kafka Stream的整體架構,並行模型,狀態存儲,以及主要的兩種數據集KStream和KTable。並且分析了Kafka Stream如何解決流式系統中... ...
  • 概述 Webhook是一個API概念,並且變得越來越流行。我們能用事件描述的事物越多,webhook的作用範圍也就越大。Webhook作為一個輕量的事件處理應用,正變得越來越有用。 準確的說webhoo是一種web回調或者http的push API,是向APP或者其他應用提供實時信息的一種方式。We ...
  • 一、元數據和 (非html5) <meta http equiv="Pragma" content="no cache"> //意思是2秒後跳轉到github //指定IE和Chrome使用最新版本渲染當前頁面 //每30秒更新document //content="with=device widt ...
  • 實驗樓上很多前端教程,這裡整理7個前端開發的小游戲教程,希望對你學習前端有所幫助~ ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...