web頁面加載、解析、渲染過程

對web項目進行優化首先得知道瀏覽器是怎麼工做的這裏推薦 how browsers work 中文版;javascript

1、瀏覽器

瀏覽器的主要功能是將用戶選擇的web資源呈現出來,它須要從服務器請求資源,並將其顯示在瀏覽器窗口中,資源的格式一般是HTML,也包括PDF、image及其餘格式。用戶用URI(Uniform Resource Identifier統一資源標識符)來指定所請求資源的位置,經過DNS查詢,將網址轉換爲IP地址。整個瀏覽器工做的流程:
  一、輸入網址。
  二、瀏覽器查找域名的IP地址。
  3. 瀏覽器給web服務器發送一個HTTP請求
  4. 網站服務的永久重定向響應
  5. 瀏覽器跟蹤重定向地址 如今,瀏覽器知道了要訪問的正確地址,因此它會發送另外一個獲取請求。
  6. 服務器「處理」請求,服務器接收到獲取請求,而後處理並返回一個響應。
  7. 服務器發回一個HTML響應
  8. 瀏覽器開始顯示HTML
  9. 瀏覽器發送請求,以獲取嵌入在HTML中的對象。在瀏覽器顯示HTML時,它會注意到須要獲取其餘地址內容的標籤。這時,瀏覽器會發送一個獲取請求來從新得到這些文件。這些文件就包括CSS/JS/圖片等資源,這些資源的地址都要經歷一個和HTML讀取相似的過程。因此瀏覽器會在DNS中查找這些域名,發送請求,重定向等;css

瀏覽器的主要組件包括

1. 用戶界面: 包括地址欄、後退/前進按鈕、書籤目錄等,也就是你所看到的除了用來顯示你所請求頁面的主窗口以外的其餘部分;html

2. 瀏覽器引擎:用來查詢及操做渲染引擎的接口;html5

3. 渲染引擎: 用來顯示請求的內容,例如,若是請求內容爲html,它負責解析html及css,並將解析後的結果顯示出來;java

4. 網絡:用來完成網絡調用,例如http請求,它具備平臺無關的接口,能夠在不一樣平臺上工做;web

5. UI 後端:用來繪製相似組合選擇框及對話框等基本組件,具備不特定於某個平臺的通用接口,底層使用操做系統的用戶接口;後端

6. JS解釋器:用來解釋執行JS代碼;瀏覽器

7. 數據存儲:H5定義了web database技術,這是一種輕量級完整的客戶端存儲技術;性能優化

 2、頁面生成過程

一、DNS服務器經過域名查找對應的web 服務器ip地址;服務器

二、瀏覽器訪問web服務器;

 這裏涉及到客戶端與服務器的tcp 三次握手與四次揮手,能夠參考上篇博文《TCP的三次握手(創建鏈接)與 四次揮手(關閉鏈接)》;

三、服務器處理完成返回html;

四、瀏覽器解析、加載頁面

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

咱們知道瀏覽器爲了體驗友好,並非文檔所有都解析才繪製到屏幕上,而是從上至下開始解析html,遇到css 會開啓線程下載css;

解析:
  一、將HTML構建成一個DOM樹(DOM = Document Object Model 文檔對象模型),DOM 樹的構建過程是一個深度遍歷過程:當前節點的全部子節點都構建好後纔會去構建當前節點的下一個兄弟節點。
  二、將CSS解析成CSS去構造CSSOM樹( CSSOM = CSS Object Model CSS對象模型)
  三、根據DOM樹和CSSOM來構造 Rendering Tree(渲染樹)。注意:Rendering Tree 渲染樹並不等同於 DOM 樹,由於一些像 Header 或 display:none 的東西就不必放在渲染樹中了。

  4.有了Render Tree,瀏覽器已經能知道網頁中有哪些節點、各個節點的CSS定義以及他們的從屬關係。
  5.下一步操做稱之爲Layout,顧名思義就是計算出每一個節點在屏幕中的位置 layout render tree。
  6.再下一步就是繪製,即遍歷render樹,並使用瀏覽器UI後端層繪製每一個節點。

性能優化中重繪、重排:
(1)Reflow(迴流/重排):當它發現了某個部分發生了變化影響了佈局,渲染樹須要從新計算。
(2)Repaint(重繪):改變了某個元素的背景顏色,文字顏色等,不影響元素周圍或內部佈局的屬性,將只會引發瀏覽器的repaint,根據元素的新屬性從新繪製,使元素呈現新的外觀。重繪不會帶來從新佈局,並不必定伴隨重排;
Reflow要比Repaint更花費時間,也就更影響性能。因此在寫代碼的時候,要儘可能避免過多的Reflow。

reflow的緣由:

(1)頁面初始化的時候;
(2)操做DOM時;
(3)某些元素的尺寸變了;
(4)若是 CSS 的屬性發生變化了。

減小 reflow/repaint

 (1)不要一條一條地修改 DOM 的樣式。與其這樣,還不如預先定義好 css 的 class,而後修改 DOM 的 className。
 (2)不要把 DOM 結點的屬性值放在一個循環裏當成循環裏的變量。
 (3)爲動畫的 HTML 元件使用 fixed 或 absoult 的 position,那麼修改他們的 CSS 是不會 reflow 的。
 (4)千萬不要使用 table 佈局。由於可能很小的一個小改動會形成整個 table 的從新佈局。

3、影響頁面渲染

css注意事項

css選擇符是從右到左進行匹配的。因此,#nav li 咱們覺得這是一條很簡單的規則,秒秒鐘就能匹配到想要的元素,因此,會去找全部的li,而後再去肯定它的父元素是否是#nav。所以,寫css的時候須要注意:

  1. dom深度儘可能淺。
  2. 減小inline javascript、css的數量。
  3. 使用現代合法的css屬性。
  4. 不要爲id選擇器指定類名或是標籤,由於id能夠惟一肯定一個元素。
  5. 避免後代選擇符,儘可能使用子選擇符。緣由:子元素匹配符的機率要大於後代元素匹配符。後代選擇符;#tp p{} 子選擇符:#tp>p{}
  6. 避免使用通配符,舉一個例子,.mod .hd *{font-size:14px;} 根據匹配順序,將首先匹配通配符,也就是說先匹配出通配符,而後匹配.hd(就是要對dom樹上的全部節點進行遍歷他的父級元素),而後匹配.mod,這樣的性能耗費可想而知.

javascript 位置

若是在解析html的時候遇到js會阻塞頁面渲染,因此通常咱們會將全部的script標籤放到頁面底部,也就是body閉合標籤以前,這能確保在腳本執行前頁面已經完成了DOM樹渲

染。儘量地合併腳本。頁面中的script標籤越少,加載也就越快,響應也越迅速。不管是外鏈腳本仍是內嵌腳本都是如此。

採用無阻塞下載 JavaScript 腳本的方法:
(1)使用script標籤的 defer、async 屬性、;
(2)使用動態建立的script元素來下載並執行代碼等異步加載等方法;

defer、async 區別:

defer、async都是異步下載,可是執行時刻不一致;

相同點:

  • 加載文件時不阻塞頁面渲染;
  • 使用這兩個屬性的腳本中不能調用document.write方法;
  • 容許不定義屬性值,僅僅使用屬性名;

不一樣點:

  • html的版本html4.0中定義了defer,html5.0中定義了async;這將形成因爲瀏覽器版本的不一樣而對其支持的程度不一樣;
  • 每個async屬性的腳本都在它下載結束以後馬上執行,同時會在window的load事件以前執行,因此就有可能出現腳本執行順序被打亂 的狀況;
  • 每個defer屬性的腳本都是在頁面解析完畢以後,按照本來的順序執行,同時會在document的DOMContentLoaded以前執行;

動態建立DOM方式

function downloadJSAtOnload() {

            var urlList = [

                "@ViewHelper.Content("/Content/plugin/alert/js/j_alert.js", "20170111")",

                "@ViewHelper.Content("/Content/js/swiper.min.js")",

                "@ViewHelper.Content("/Content/js/imageview_new.js", "201702271")"

            ];

            for (var i = 0; i <= urlList.length - 1; i++) {

                var element = document.createElement("script");

                element.src = urlList[i];

                document.body.appendChild(element);

            }

        }
相關文章
相關標籤/搜索