天天看點

從浏覽器位址欄輸入url到顯示頁面的步驟?

浏覽器從輸入URL到頁面加載的全過程

從輸入URL到頁面加載的主幹流程如下:

  • 浏覽器的位址欄輸入URL并按下回車。
  • 浏覽器查找目前URL的DNS緩存記錄。
  • DNS解析URL對應的IP。
  • 根據IP建立TCP連接配接(三次握手)。
  • HTTP發送請求。
  • 伺服器處理請求,浏覽器接收HTTP響應。
  • 渲染頁面,建構DOM樹。
  • 關閉TCP連接配接(四次握手)。

1.首先在浏覽器中輸入URL

  • 我們常見的URL是這樣的:http://www.baidu.com,這個域名由三部分組成:協定名、域名、端口号,這裡端口是預設是以隐藏。除此之外URL還會包含一些路徑、查詢和其他片段,例如:http://www.tuicool.com/search?kw=%E4%。我們最常見的的協定是HTTP協定,除此之外還有加密的HTTPS協定、FTP協定、FILe協定等等。URL的中間部分為域名或者是IP,之後就是端口号了。通常端口号不常見是因為大部分的都是使用預設端口,如HTTP預設端口80,HTTPS預設端口443。
  • 查找緩存:浏覽器先檢視浏覽器緩存-系統緩存-路由緩存中是否有該位址頁面,如果有則顯示頁面内容。如果沒有則進行下一步。
  • 浏覽器緩存:浏覽器會記錄DNS一段時間,是以,隻是第一個地方解析DNS請求;
  • 作業系統緩存:如果在浏覽器緩存中不包含這個記錄,則會使系統調用作業系統, 擷取作業系統的記錄(儲存最近的DNS查詢緩存);
  • 路由器緩存:如果上述兩個步驟均不能成功擷取DNS記錄,繼續搜尋路由器緩存;
  • ISP緩存:若上述均失敗,繼續向ISP搜尋。

2.DNS域名解析

我們知道在位址欄輸入的域名并不是最後資源所在的真實位置,域名隻是與IP位址的一個映射。網絡伺服器的IP位址那麼多,我們不可能去記一串串的數字,是以域名就産生了,域名解析的過程實際是将域名還原為IP位址的過程。

首先浏覽器先檢查本地hosts檔案是否有這個網址映射關系,如果有就調用這個IP位址映射,完成域名解析。

如果沒找到則會查找本地DNS解析器緩存,如果查找到則傳回。

如果還是沒有找到則會查找本地DNS伺服器,如果查找到則傳回。

最後疊代查詢,按根域伺服器 ->頂級域,.cn->第二層域,hb.cn ->子域,www.hb.cn的順序找到IP位址。

  • DNS域名解析:浏覽器向DNS伺服器發起請求,解析該URL中的域名對應的IP位址。DNS伺服器是基于UDP的,是以會用到UDP協定。

3.建立TCP連接配接: 解析出IP位址後,根據IP位址和預設80端口,和伺服器建立TCP連接配接

發起HTTP請求: 浏覽器發起讀取檔案的HTTP請求,,該請求封包作為TCP三向交握的第三次資料發送給伺服器

伺服器響應請求并傳回結果:伺服器對浏覽器請求做出響應,并把對應的html檔案發送給浏覽器

關閉TCP連接配接: 通過四次揮手釋放TCP連接配接

浏覽器渲染:用戶端(浏覽器)解析HTML内容并渲染出來,浏覽器接收到資料包後的解析

**建構DOM樹:**詞法分析然後解析成DOM樹(dom tree),是由dom元素及屬性節點組成,樹的根是document對象

  • 建構CSS規則樹:生成CSS規則樹(CSS Rule Tree)
  • 建構render樹:Web浏覽器将DOM和CSSOM結合,并建構出渲染樹(render tree)
  • 布局(Layout):計算出每個節點在螢幕中的位置
  • 繪制(Painting):即周遊render樹,并使用UI後端層繪制每個節點。

JS引擎解析過程:

調用JS引擎執行JS代碼(JS的解釋階段,預處理階段,執行階段生成執行上下文,VO,作用域鍊、回收機制等等)

  • 建立window對象:window對象也叫全局執行環境,當頁面産生時就被建立,所有的全局變量和函數都屬于window的屬性和方法,而DOM Tree也會映射在window的doucment對象上。當關閉網頁或者關閉浏覽器時,全局執行環境會被銷毀。
  • 加載檔案:完成js引擎分析它的文法與詞法是否合法,如果合法進入預編譯
  • 預編譯:在預編譯的過程中,浏覽器會尋找全局變量聲明,把它作為window的屬性加入到window對象中,并給變量指派為’undefined’;尋找全局函數聲明,把它作為window的方法加入到window對象中,并将函數體指派給他(匿名函數是不參與預編譯的,因為它是變量)。而變量提升作為不合理的地方在ES6中已經解決了,函數提升還存在。
  • 解釋執行:執行到變量就指派,如果變量沒有被定義,也就沒有被預編譯直接指派,在ES5非嚴格模式下這個變量會成為window的一個屬性,也就是成為全局變量。string、int這樣的值就是直接把值放在變量的存儲空間裡,object對象就是把指針指向變量的存儲空間。函數執行,就将函數的環境推入一個環境的棧中,執行完成後再彈出,控制權交還給之前的環境。JS作用域其實就是這樣的執行流機制實作的。

浏覽器重繪與重排的差別?

  • 重排/回流(Reflow):當DOM的變化影響了元素的幾何資訊,浏覽器需要重新計算元素的幾何屬性,将其安放在界面中的正确位置,這個過程叫做重排。表現為重新生成布局,重新排列元素。
  • 重繪(Repaint): 當一個元素的外觀發生改變,但沒有改變布局,重新把元素外觀繪制出來的過程,叫做重繪。表現為某些元素的外觀被改變
  • 單單改變元素的外觀,肯定不會引起網頁重新生成布局,但當浏覽器完成重排之後,将會重新繪制受到此次重排影響的部分
  • 重排和重繪代價是高昂的,它們會破壞使用者體驗,并且讓UI展示非常遲緩,而相比之下重排的性能影響更大,在兩者無法避免的情況下,一般我們甯可選擇代價更小的重繪。
  • 『重繪』不一定會出現『重排』,『重排』必然會出現『重繪』。

如何觸發重排和重繪?

任何改變用來建構渲染樹的資訊都會導緻一次重排或重繪:

  • 添加、删除、更新DOM節點
  • 通過display: none隐藏一個DOM節點-觸發重排和重繪
  • 通過visibility: hidden隐藏一個DOM節點-隻觸發重繪,因為沒有幾何變化
  • 移動或者給頁面中的DOM節點添加動畫
  • 添加一個樣式表,調整樣式屬性
  • 使用者行為,例如調整視窗大小,改變字号,或者滾動。

如何避免重繪或者重排?

  • 集中改變樣式,不要一條一條地修改 DOM 的樣式。
  • 不要把 DOM 結點的屬性值放在循環裡當成循環裡的變量。
  • 為動畫的 HTML 元件使用 fixed 或 absoult 的 position,那麼修改他們的 CSS 是不會 reflow 的。
  • 不使用 table 布局。因為可能很小的一個小改動會造成整個 table 的重新布局。
  • 盡量隻修改position:absolute或fixed元素,對其他元素影響不大
  • 動畫開始GPU加速,translate使用3D變化

    在這裡插入代碼片

  • 提升為合成層

将元素提升為合成層有以下優點:

  • 合成層的位圖,會交由 GPU 合成,比 CPU 處理要快
  • 當需要 repaint 時,隻需要 repaint 本身,不會影響到其他的層
  • 對于 transform 和 opacity 效果,不會觸發 layout 和 paint

    提升合成層的最好方式是使用 CSS 的 will-change 屬性:

#target {
will-change: transform;
}