[譯]從輸入URL到頁面呈現的超詳細過程——第一步:獲取資源

wangds發表於2019-01-28

原文連結:From URL to Interactive
原文作者:agustafson
譯者:wangds

這是一個系列文章,分為四個部分介紹了從輸入URL到頁面呈現的詳細過程

  • 客戶端從伺服器獲取資源(Server to Client)
  • 標籤轉化成DOM的過程(tags to DOM)
  • CSS解析的過程(braces to pixels)
  • 編譯執行javascript的過程(var to JIT)

本篇翻譯的是第一部分:Server to Client

每當我們在位址列中輸入URL或者點選一個連結的時候,實質就是對瀏覽器(客戶端)下達一道指令去指定的位置(伺服器)獲得我們想要的資源。獲取資源是瀏覽器展示web頁面的第一步工作。

獲取資源是一個過程,這個過程可以拆解成如下幾個步驟。

1.瀏覽器修正傳輸協議(CHECK FOR HSTS)

當瀏覽器接收到URL後,瀏覽器首先要修正URL的傳輸協議(http or https)。之所以採用修正這個詞,是因為瀏覽器中有兩個列表:預載入 HSTS列表和瀏覽器曾經訪問過的HSTS列表,凡是在這兩個列表內的地址,瀏覽器都會將傳輸協議改成HTTPS。舉個例子,即使你在瀏覽器裡輸入了http://www.bing.com這個地址,最後訪問的都是https://www.bing.com。

2.瀏覽器檢查服務工作執行緒(CHECK FOR SERVICE WORKERS)

接下來,瀏覽器要確認Service Worker是否能處理這個請求。Service Worker本質上充當了Web應用程式與瀏覽器之間的代理伺服器,也可以在網路可用時作為瀏覽器和網路間的代理。Service Worker通過攔截並代理請求的方式,從指令碼控制的快取內獲得資源。

使用者首次訪問具有Service Worker功能的網站時,Service Worker會立刻被下載(之後每24小時它至少會被下載一次)。下載完成後Service Worker將依次進行安裝和啟用。如果網站有一個Service Worker處於啟用狀態,新下載的Service Worker在安裝完成後不會立即啟用而是處於等待狀態。只有當網站不依賴舊的Service Worker後,新的Service Worker才會啟用。Service Worker是完全非同步的。

如果沒有Service Worker,瀏覽器將會訪問網路層,直接進行下一步工作。

3.瀏覽器檢查網路快取(CHECK THE NETWORK CACHE)

在這一步中,瀏覽器首先確定本次請求的資源是否已經存在於自己的快取中。如果瀏覽器是第一訪問這個網站,肯定沒有快取,然後瀏覽器將傳送請求至伺服器,在請求頭中新增Cache-Control這個欄位用來制定本次請求關於快取的規則。Cache-Control常見的取值有max-age(快取內容失效時限)、no-store(是否開啟快取)、no-cache(使用快取時是否需要與伺服器驗證)等。每次從瀏覽器的快取中使用設定了no-cache資源前,都要傳送一個驗證請求到伺服器,驗證快取中的資源是否是最新的。這個驗證快取的請求頭中包含If-Modified-Since(時間判定)或者包含If-None-Match(資源版本號),伺服器接收到請求後根據修改時間或者最新版本號來斷定瀏覽器中的資源是不是最新的,如果瀏覽器中的資源是最新的則響應HTTP 304,告知瀏覽器繼續使用之前的快取;不是最新的則返回HTTP 200,同時響應最新的資源給瀏覽器,更新快取。

4.瀏覽器檢測連線(CHECK FOR CONNECTION)

這一步的工作是解析DNS獲取正確的IP地址,解析域名的第一步是瀏覽器查詢本機硬碟HOST檔案是否有對應的IP地址,如果本機硬碟HOST檔案內沒有,瀏覽器會傳送一個DNS請求到本地DNS伺服器(Internet服務提供商託管,中國的電信聯通等),本地DNS伺服器會首先查詢自己的快取記錄,如果沒有將繼續傳送請求至DNS根伺服器,逐級查詢到正確的IP地址。

有些時候,瀏覽器可以預先知道將要訪問哪些資源,提前與這些資源進行連線。方法就是在頁面的link標籤內新增Resource Hint來告知瀏覽器哪些資源需要預先連線載入。Resource HintDNS PrefetchPreconnectPrefetchPrerender四種。舉個應用例子,當我們在搜尋引擎中搜尋東西的時候,結果頁面上會展示大量的相關連結。瀏覽器可以使用Resource Hint將最靠前的搜尋結果進行預連線和預下載,這樣當我們點選這些靠前連結的時候,開啟速度將更快。

5.瀏覽器與伺服器建立連結(ESTABLISH CONNECTION)

到了這一步,客戶端(也就是瀏覽器)已經正式與伺服器建立了連線。如果我們使用TLS,則需要執行TLS握手來驗證伺服器提供的證照。

6.瀏覽器傳送請求到伺服器(SEND THE REQUEST TO THE SERVER)

通常來說,瀏覽器發給伺服器的第一個請求是最基礎的頁面請求。伺服器會將一個HTML檔案傳送給瀏覽器。

7.瀏覽器處理響應(HANDLE THE RESPONSE)

瀏覽器接收到來自伺服器的響應資源後,將對這些響應資源進行分析。首先,瀏覽器將檢視Response header。如果瀏覽器檢視Response header表示需要重定向(例如採用 Location header的方法),瀏覽器拿到重定向的地址後,將重新從第一步修正傳輸協議(CHECK FOR HSTS)開始工作。

如果伺服器的響應資源進行了壓縮,瀏覽器還需要對這些資源進行解壓。

另外,瀏覽器開始解析響應資源的時候,同時開始對這些資源進行快取。

接下來,瀏覽器通過判斷響應內資源的MIME型別確定用什麼樣的方式來載入資源。例如,在瀏覽器解析HTML的時候,碰到影象檔案就以image物件的方式載入。另外瀏覽器在解析HTML時(未生成render樹),還會繼續下載響應內的資源。這一部分的知識將在下篇文章內詳細講解。

至此,瀏覽器將會把這次訪問的URL放入瀏覽器的歷史記錄裡,我們可以通過瀏覽器的前進和後退功能訪問他們。

下面的流程圖的展示了1-7的步驟內容:

流程圖

正如我們所知道的,還有很多後續需要請求的資源,例如圖片資源、css資源、JavaScript資源。以及css資源內又包含的圖片或者使用import()AJAX引用的其他資源等等。這些全部的資源才構造了具有互動性的頁面。我們所有請求的資源都遵循上面的流程圖,當然也遵循瀏覽器的快取策略。

細聊瀏覽器快取(Caching)

前文已經提到,瀏覽器管理著HTTP快取,快取中的資源用來快速展示我們曾經訪問過的網站。快取中儲藏著類似於網站圖示、基礎JavaScript檔案等不經常變動的資源。合理的使用快取既可以減少網路請求的數量又可以加快頁面的載入速度。

另外,HTTP快取也是有限度的。瀏覽器通過Response header頭內的Cache-Control來判斷需要快取哪些資源和快取資源的時限。比如瀏覽器可以通過Cache-Control: no-store來判斷本次請求的資源是不需要快取的,這種不快取的內容一般是指需要頻繁變動的資源。又比如Cache-Control: immutable用來斷定本次請求的資源是永久不變的。在使用Cache-Control: immutable的時候,作者建議用不同的URL來對應同一資源的不同版本,以便瀏覽器快取的資源不受影響。

當然,瀏覽器中不僅僅有HTTP快取這一種快取。我們可以通過JavaScript進行程式化快取。這就是我們第二步中提到的Service Worker,Service Worker可以攔截請求並返回Service Worker快取的資源。Service Worker程使網站的快取更具有靈活性。另外,每個網站的程式化快取都是獨立,這些快取與網站是一一對應的關係。

源的概念(Origin model)

同源指的是通訊協議、域名、埠完全相同。舉個例子,https://www.bing.com:443中https是通訊協議,www.bing.com是域名,443是埠。https://www.bing.com:443和 http://www.bing.com:80就是不同源的。

同源是瀏覽器中非常重要的一個概念,隔離開來的資料變得更加安全。在大多數情況下,瀏覽器為了安全考慮都採用同源策略。在上面的兩個例子中https://www.bing.com:443和 http://www.bing.com:80都無法檢視對方的快取。

假如bing.com想呼叫一個microsoft.com的JavaScript資源,正常情況下瀏覽器會因為同源策略而不允許。這個時候可以採用CORS(Cross-Origin Resource Sharing)方法來進行跨域訪問。microsoft.com伺服器將進行一個宣告表示bing.com可以訪問哪些資源。

結束語

以上就包含了資源從伺服器到客戶端的全部內容。下一篇文章我們將聊聊HTML標籤是如何轉化成DOM的。

限於本人水平有限,文中如有錯誤感謝您指正。

相關文章