對於面試的大部分前端開發者來講,對瀏覽器的瞭解也算是隻知其一;不知其二,由於咱們一開始前端以爲,咱們開發中一般使用瀏覽器來顯示和調試頁面用的,不會涉入到太過的相關瀏覽器工做原理知識。前端
這你就大錯特錯了,雖然瀏覽器默默的爲咱們工做,可是有關瀏覽器的工做原理不但在你就業前端面試中屬於重中之重,也是在前端優化中佔有很大比重。做爲一個前端開發若是不瞭解瀏覽器的工做原理,只能永遠停留在前端「切圖仔」水平。面試
PS:前幾天還有個讀者和小鹿說,以前看到小鹿朋友圈發過這個這個導圖,當時沒當回事,次日面試居然問到了。算法
學習瀏覽器工做原理是爲了可以運用到實際項目中,好比前端的性能優化以及錯誤排查,都會涉及到瀏覽器相關的知識,因此掌握瀏覽器的工做原理是必不可缺的,相信你學完以後,可以對你的我的能力和見識會有很大的提高。編程
瀏覽器涉及到的知識點很是多並且很是重要,文章中可能其中有不足和錯誤的地方,也歡迎各位指出!瀏覽器
咱們由淺入深的去了解瀏覽器的工做原理。首先學習一個事物要知道它是什麼,它要完成一個什麼樣的事情,也就是擁有什麼樣的職責。緩存
對於瀏覽器來講,表面上看來,咱們輸入了 URL,而後等待幾秒瀏覽器就展示出咱們想要訪問的網址內容了。對沒錯,這就是瀏覽器的職責所在。這只是停留在了表面,要想深刻知道瀏覽器在這個階段發生了什麼?須要咱們進一步探索瀏覽器的工做原理。性能優化
因此說,不管是面試仍是實際工做中,瀏覽器無時不刻和咱們打交道。那咱們就要從在瀏覽器輸入 URL 開始提及,直到瀏覽器最後展示出網站內容,這個過程瀏覽器作了哪些工做,又是如何工做的呢?bash
咱們會詳細分爲如下幾大模塊進行系統的講解:服務器
一、DNS 解析網絡
二、TCP 鏈接
三、HTTP 請求
四、構建 DOM 樹
五、構建 CSSOM 樹
六、生成渲染樹
七、合成、繪製
其中有些部分咱們以前的文章已經分享過,因此也不過到陳述,到時候會鞏固一下,重點咱們放在瀏覽器的渲染原理上,這也是咱們之後在學習前端優化中的重點。
在以前的文章 TCP 三次握手中提到,要想獲得接收方的 MAC 地址,須要經過對方的 IP 地址獲取,對方的 IP 須要經過 DNS 解析。
所謂的 DNS 解析就是將咱們輸入在網頁地址欄的 URL 經過 DNS 解析成 IP 地址。DNS 就是將域名轉化成 ip 地址的過程。那麼這個過程會發生什麼呢?和小鹿一塊兒深刻探究一下。
首先瀏覽器會調用一個庫函數,檢測本地的 hosts 文件(能夠認爲是電腦本地的一個地址映射文件),從該文件中查看是否有對應的該域名的 IP 地址,這個過程是在系統緩存中查找是否存在該域名對應的 IP 地址。
好比在瀏覽器的地址欄中輸入小鹿的博客網址(www.xiaolu.com),而後回車,此時瀏覽器拿着這個域名去本地電腦的一個名爲 hosts 文件中查詢是否存在該域名所對應的 IP 地址,若是有,就返回給瀏覽器,若是沒有,咱們繼續往下進行。
若是系統緩存沒有,就會向 DNS 服務器發送請求,而網絡服務通常都會先通過路由器以及網絡服務商(電信),因此會先查詢路由器緩存,而後再查詢 ISP 的 DNS 緩存。
PS:ISP緩存,自己是一種寬帶接入提供商給網頁批量訪問加速的技術。ISP會將當前訪問量較大的網頁內容放到ISP服務器的緩存中,當有新的用戶請求相同內容時,能夠直接從緩存中發送相關信息,沒必要每次都去訪問真正的網站,從而加快了不一樣用戶對相同內容的訪問速度,同時也能節省網間流量結算成本。
若是路由器緩存和 ISP 的 DNS 緩存仍是沒有的話,咱們就進行 DNS 遞歸查詢。從根域名服務器開始查詢,而後再到頂級域名服務器,最後到主域名服務器依次查詢。
可是這裏有兩種查詢方式,不只僅有遞歸查詢一種方式,還有一個查詢方式是迭代查詢,兩種查詢方式的區別是什麼呢?
迭代查詢:DNS 收到請求時,而不是直接返回查詢結果,而是告訴客戶端另外一臺 DNS 服務器地址。而後客戶端再向這臺的 DNS 服務器提交請求,依次循環。
遞歸查詢:當 DNS 服務器收到請求時,就會檢查 DNS 緩存,若是沒有就會詢問其餘服務器,並將返回的查詢結果返回客戶端。
咱們前端會在性能優化的使用用到 DNS 的相關知識,咱們在這稍微提一下,如何進行 DNS 優化呢?
DNS 查詢經歷不少步驟,查詢很慢。瀏覽器獲取到 IP 地址後,通常都會加到瀏覽器的緩存中,本地的 DNS 緩存服務器,也能夠去記錄。
另外使用 DNS 負載均衡,一般咱們的網站應用各類雲服務,DNS 系統根據每臺機器的負載量,地理位置的限制等等,去提供高效快速的 DNS 解析服務。
咱們經過 DNS 查詢到 IP 地址以後,咱們就開始打算與服務器創建鏈接,爲接下來的數據傳輸作準備,這部分在以前的文章中寫的很是詳細,必定要去看哦。
咱們客戶端與服務端經過 TCP 的三次握手創建鏈接以後,客戶端開始向服務器主動發起請求。
PS:對於 HTTP 協議,咱們會在後邊單獨拿出一篇文章來詳細介紹它的發展史,這裏咱們只涉及到 HTTP 的請求相關的內容。
服務端接收到客戶端發送的信息,就返回響應信息和文件。客戶端如何判斷服務端是否成功返回了呢?就須要下列的一些狀態碼來識別,一樣前端作的工做也是經過狀態碼來判斷當前響應狀態。
1XX(信息性狀態碼) : 服務器正在處理請求中。
2XX (成功狀態碼): 請求處理完畢。
3XX (重定向狀態碼): 須要附加操做以完成請求。
301:永久性重定向。該狀態碼錶示請求的資源已被分配了新的 URI,之後使用該資源,使用如今所指 URI。
302:臨時性重定向。表示該狀態碼被分配了新的 URI,但願用戶本次可以使用新的 URI 訪問。
304:服務器資源未改變,可直接使用客戶端未過時的緩存。
4XX (客戶端錯誤狀態碼): 服務器沒法處理請求。
400:該請求報文中有語法錯誤。
403:沒有資源的訪問權限。
404:找不到資源。
5XX (服務端錯誤狀態碼): 服務器處理請求出錯。
500:服務器發生錯誤
503:服務器超荷載或正在維護。
遠程服務器找到資源並使用 HTTP 響應返回該資源,值爲 200 的 HTTP 響應狀態表示一個正確的響應。
服務器將 HTML、CSS、JS文件轉化爲 0,1字節數據在網絡中傳輸給瀏覽器,瀏覽器經過判斷狀態碼開始接收、解析文件,這開始運用到瀏覽器的渲染原理。
首先瀏覽器要作的就是獲取 HTTP 的 Request 的 body 中字符串(字符流)的 HTML 文本,進行解析並構建 DOM 樹。
將字符流轉化爲字符串以後,瀏覽器開始進行詞法分析,雖然這個名詞咱們不熟悉,可是咱們要知道,一個 HTML 字符串咱們要拆分開才能構建 DOM 樹,詞法分析就是將字符串拆分紅的過程。將字符串轉化爲的 token(標記) —— token 做爲代碼的最小單位,也就是拆分後的結果,這個過程咱們稱爲標記化。
咱們將字符串拆解以後,而後將這些標記轉化爲 Node 結點,瀏覽器根據不一樣的結點開始構建一棵 DOM 樹。這就是整個 DOM 樹構建的過程,其中還涉及到不少的細節,好比詞法分析是如何一個過程(狀態機),有興趣的小夥伴能夠詳細查看英文文檔,在文章底部。
瀏覽器已經把 HTML 文件轉化爲了 DOM 樹,下面就對 CSS 樣式文件進行解析,構建成 CSSOM 樹。這個過程和上述構建 DOM 樹的過程有點類似,可是其中 CSSOM 樹的構建更加的耗時。下面咱們來看看如何耗時的?
瀏覽器經過遞歸的方式 DOM 樹爲結點設置樣式。經過先找到具體的標籤,而後遞歸找到設置的上級標籤,最後肯定選擇器選擇的所選標籤的樣式。
好比下邊的例子,瀏覽器是如何肯定結點的樣式的呢?
1 <div>
2 <span>
3 <p>小鹿動畫學編程,一天一篇動畫餵飽你!</p>
4 </span>
5 <p>你好,小鹿!</p>
6 </div>
7
8
9 div span p{
10 color: red;
11 font-size: 12px;
12 }
13 div {
14 background:red;
15 }
複製代碼
首先在 HTML 中找到 p 標籤,一共有兩個地方,而後按照樣式的繼續遞歸中找具備父節點的 p,咱們只好把第二個 p 過濾掉,而後繼續向上找父節點 div,匹配成功,而後將樣式設置到結點上。
咱們經過上邊的動畫,能夠知道爲何構建 CSSOM 樹的時候很是耗時了,咱們在寫代碼的時候能夠作出優化,因此應該避免書寫過於具體的 CSS 選擇器,少一些添加無心義的 HTML 標籤,有利於提升習頁面的性能。
咱們分別將上邊生成的 DOM 和 CSSOM 樹進行合併,生成咱們的渲染樹。可是在合併的時候,並非二者簡單的進行結合,由於有些結點咱們並不須要顯示,還記得有一個 display:none 屬性嗎?若是某結點的樣式有這個屬性,就不會出如今渲染樹中。
瀏覽器在生成渲染樹的時候,就會根據渲染樹進行佈局,調用 GPU 進行繪製,而後合成圖層,最後顯示在屏幕上。
經過上邊的對瀏覽器工做原理的介紹,相信你對瀏覽器有了新的認識和簡介,可是隻看上邊的知識還徹底不能深刻到底層,若是還想要進行深刻的對瀏覽器的工做原理進行研究,能夠英文文檔《How Browsers Work》,已經有人把它翻譯成了中文,可是我本身又翻譯了一遍。
第一,提升本身閱讀英文文檔的能力;
第二,從中學會提取關鍵的內容。
雖然翻譯過程當中遇到不少問題,可是相信你翻譯完以後,對你又有新的收穫和認識,更重要的是你的能力又比別人提高了 —— 更況且我這個英語四級沒過的人都堅持翻譯下來了呢!
文章+動畫寫了好幾個小時,不妨點贊支持一下。嘻嘻,你不點贊說明你很自私,你怕那麼好的文章讓別人也看到。開個小小玩笑。
做者Info:
【做者】:小鹿
【原創公衆號】:小鹿動畫學編程。
【簡介】:和小鹿同窗一塊兒用動畫的方式從零基礎學編程,將 Web前端領域、數據結構與算法、網絡原理等通俗易懂的呈獻給小夥伴。先定個小目標,原創 1000 篇的動畫技術文章,和各位小夥伴共同努力一塊兒學習!公衆號回覆 「資料」 送一從零自學資料大禮包!
【轉載說明】:轉載請說明出處,謝謝合做!~