前端工程師必須知道系列之:從使用者輸入URL到頁面載入完成到底發生了什麼?

MasonEast發表於2019-03-15
我認為一個好的前端工程師不是能完成各種需求和互動,而是能夠將信**息快速並且以一種友好的方式**傳遞給使用者。
所以當使用者輸入網址後,我們的戰鬥就開始了。
在戰鬥開始之前,先讓我們一起來了解一下一次完整的請求都有哪些過程,只有這樣,我們才能知道仗該怎麼打。
複製程式碼

文章最後有彩蛋~

第一個過程: DNS解析 當使用者輸入網址後,機器首先會把網址轉化成計算機能識別的地址,即IP地址。 DNS解析過程是一個遞迴查詢的過程。 它首先會在本地域名伺服器中查詢IP地址,如果沒有找到,本地域名伺服器會向根域名伺服器傳送一個請求,如果再沒有還會往上查詢,直到找到對應的IP地址。

第二個過程:準備HTTP請求 這個過程就是構建HTTP請求報文並通過TCP協議傳送到伺服器指定埠。一個請求報文分為三個部分: 請求行,請求頭和請求正文。 這裡就不詳細介紹HTTP請求了,不瞭解的可以參考《圖解HTTP》一書,相當不錯!

第三個過程:TCP連線 當客戶端HTTP請求準備完畢之後,接下來就是傳送給伺服器端,而HTTP協議依賴於TCP作為其傳輸層協議的。這裡簡單說下網際網路協議分為四層: 應用層(HTTP協議就在這一層) 傳輸層 網路層 資料鏈路層 HTTP請求會從應用層往上走,直到伺服器端,然後伺服器端會反向將響應資料傳回客戶端,這些《圖解HTTP》都會講到。

第四個過程:伺服器端處理請求並返回HTTP報文

這部分主要是後端一塊的事,有興趣的可以瞭解一下。
複製程式碼

第五個過程:瀏覽器解析並渲染頁面

這個過程可以說是我們前端的最主要的戰場,也是我們必須要了解的過程!

瀏覽器在收到伺服器返回的資料裡,一般會包含HTML,CSS和JS檔案。那麼,瀏覽器是如何完成解析渲染的呢?

首先,需要明確一點:瀏覽器是邊解析邊渲染的。

關於HTML,CSS,JS檔案,瀏覽器解析順序完全是根據返回資料來決定的。

一般情況下,大家都會把CSS放在HTML的前面,而JS放在最後面,因為CSS會定義HTML標籤的樣式,所以要在前面,而JS放在後面的原因是,當瀏覽器解析引擎解析JS時,HTML的渲染過程會被暫停,因為JS有可能會修改DOM結構,這就意味著JS執行完成前,後面的wHTML渲染是沒有意義的,有可能會被重構。這就是JS會影響HTML渲染的根本原因。直到JS檔案解析完畢,這樣對使用者體驗傷害極大。

再說下,當瀏覽器解析HTML和CSS檔案時,會分別構建DOM樹和渲染樹,等到渲染樹構建完成後,瀏覽器開始繪製螢幕,這個過程涉及到兩個比較重要的概念:就是reflow(迴流)和repain(重繪)

DOM節點中的各個元素都是以盒模型的形式存在的,盒模型簡單理解即:content,padding,border,margin。而每個盒模型都有它的大小和位置,這些都需要瀏覽器去計算得出,這個計算的過程就是reflow(迴流);當盒模型確定下來之後,瀏覽器就會開始繪製盒模型裡面的內容,即content,這個過程就稱為repain(重繪)。頁面在首次載入時必然會經歷這兩個過程,而這兩個過程是非常消耗效能的,所以我們應該儘可能的減少reflow和repain。

再講下JS的解析過程:

JS的解析是由瀏覽器的JS解析引擎完成的,我們都知道,JavScript是單執行緒執行的。也就是說,一次只能做一件事,所有的事情都必須排隊,一個一個的進行,但是當某些事情比較麻煩,會耽擱較多時間的時候,這樣就會造成執行緒阻塞,為了解決這個問題,JavaScript的執行機制引入了同步任務和非同步任務,這樣,就相當於在Javascript的單執行緒(也稱為執行棧)的旁邊加了任務佇列(task queue)。同步任務會放在執行棧上去執行,在執行過程中如果遇到了非同步程式碼(如setTimeout,Promise,ajax等),瀏覽器會將這些程式碼放到一個幕後執行緒中去等待,不阻塞主執行緒的執行,主執行緒繼續走,當幕後執行緒準備好了,會將它的回撥函式放到任務佇列中等待執行。當主執行緒執行完所有程式碼後,它就會回頭檢查任務佇列是否有任務要執行,如果有就將任務放到執行棧中執行,如果沒有,它就會進入迴圈等待任務到來。這就是事件迴圈(event loop)

當任務佇列有多個任務,執行順序問題: 其實js有兩個任務佇列:

Macrotask Queue:主要是處理巨集任務(如seTimeout,setInterval,使用者互動操作,UI渲染等) Microtask Queue:主要處理微任務(如Promise,process.nextTick(nodejs)) 執行順序是先檢查兩個佇列,先從Macrotask佇列執行等待最長的任務,然後執行Microtask佇列等待最長的,依次迴圈執行。

瀏覽器在解析過程中,如果遇到需要請求外部資源時(如圖片,JS檔案等),瀏覽器將重複上面的過程,請求過程是非同步的,不會影響HTML文件的載入。

有一點忘記說了,就是CSS檔案的載入不影響JS檔案的載入,但是卻影響JS檔案的執行。因為JS程式碼可能會涉及到對DOM裡面元素樣式的修改。所以

JS程式碼執行前瀏覽器必須保證CSS檔案已經下載並載入完畢

最後給兄弟們分享下《圖解HTTP》的電子版:連結: pan.baidu.com/s/1SGxQLZbl… 提取碼:w0r9

相關文章