瀏覽器是如何工作的?

0. 為什么要了解瀏覽器是如何工作的

想要寫出一個最佳實踐的頁面,要實現性能優化,就要好好了解了解瀏覽器的工作原理。

  • 了解瀏覽器如何進行加載,可以在引用外部樣式表文件、外部 JavaScript 文件時,將他們放到合適的位置,使瀏覽器以最快的速度及合理的順序將文件加載完畢。
  • 了解瀏覽器如何進行解析,可以在構建 DOM 結構,組織 CSS 選擇器時,選擇最優的寫法,提高瀏覽器的解析效率。
  • 了解瀏覽器如何進行渲染,明白渲染的過程,在設置元素屬性,編寫 JavaScript 文件時,可以減少 “reflow” “repaint” 的消耗。

1. 瀏覽器的主要功能及構成

瀏覽器的主要功能 是將用戶選擇的 web 資源呈現出來,它需要從服務器請求資源,并將其顯示在瀏覽器窗口中,資源的格式通常是 HTML,也包括 PDF、image 及其他格式。用戶用 URI(Uniform Resource Identifier 統一資源標識符)來指定所請求資源的位置。

瀏覽器的主要構成

瀏覽器的主要組件包括:

  1. 用戶界面 - 包括地址欄、后退/前進按鈕、書簽目錄等,也就是你所看到的除了用來顯示你所請求頁面的主窗口之外的其他部分。
  2. 瀏覽器引擎 - 用來查詢及操作渲染引擎的接口。
  3. 渲染引擎 - 用來顯示請求的內容,例如,如果請求內容為 html,它負責解析 html 及 css,并將解析后的結果顯示出來。
  4. 網絡 - 用來完成網絡調用,例如 http 請求,它具有平臺無關的接口,可以在不同平臺上工作。
  5. UI 后端 - 用來繪制類似組合選擇框及對話框等基本組件,具有不特定于某個平臺的通用接口,底層使用操作系統的用戶接口。
  6. JS 解釋器 - 用來解釋執行 JS 代碼。
  7. 數據存儲 - 屬于持久層,瀏覽器需要在硬盤中保存類似 cookie 的各種數據,HTML5 定義了 web database 技術,這是一種輕量級完整的客戶端存儲技術。
瀏覽器主要組件

2. 瀏覽器的渲染

2.1 渲染引擎簡介

渲染引擎的職責就是渲染,即在瀏覽器窗口中顯示所請求的內容。

默認情況下,渲染引擎可以顯示 html、xml 文檔及圖片,它也可以借助插件(一種瀏覽器擴展)顯示其他類型數據,例如使用 PDF 閱讀器插件,可以顯示 PDF 格式,這里先不討論插件及擴展,只討論渲染引擎最主要的用途——顯示應用了 CSS 之后的 html 及圖片。

2.2 渲染流程

渲染引擎基本流程

渲染引擎首先通過網絡獲得所請求文檔的內容,通常以 8K 分塊的方式完成,即以 8K 每塊下載 html 頁面。

然后解析頁面生成 DOM 樹,遇到 CSS 標簽或 JS 腳本標簽就新起線程去下載他們,并繼續構建 DOM。

CSS 下載完后解析為 CSS 規則樹,瀏覽器結合 CSS 規則樹和 DOM 樹生成 Render Tree。Render Tree 由一些包含有顏色和大小等屬性的矩形組成,它們將被按照正確的順序顯示到屏幕上。

JavaScript 下載后可以通過 DOM API 修改 DOM,通過 CSSOM(CSS Object Model) API 修改樣式作用域 Render Tree。注意:構建 CSSOM 會阻塞 JavaScript 的執行,JavaScript 的執行也會阻塞 DOM 的構建。

每次修改會造成 Render Tree 的重新布局和重繪。只要修改 DOM 或修改了元素的形狀或大小,就會觸發 Reflow,單純修改元素的顏色只需 Repaint 一下(調用操作系統 Native GUI 的 API 繪制)。

Render Tree 構建好了之后,將會執行布局過程,它將確定每個節點在屏幕上的確切坐標。再下一步就是繪制,即遍歷 Render Tree,并使用 UI 后端層繪制每個節點。也可用下圖描述:

渲染引擎流程

值得注意的是,這個過程是逐步完成的,為了更好的用戶體驗,渲染引擎將會盡可能早的將內容呈現到屏幕上,并不會等到所有的 html 都解析完成之后再去構建和布局 Render Tree。它是解析完一部分內容就顯示一部分內容,同時,可能還在通過網絡下載其余內容。

2.3 reflow 與 repaint

現在再表述一下 HTML 頁面加載和解析的流程:

  1. 用戶輸入網址(假設是個 html 頁面,并且是第一次訪問),瀏覽器向服務器發出請求,服務器返回 html 文件;
  2. 瀏覽器開始載入 html 代碼,發現 <head> 標簽內有一個 <link> 標簽引用外部 CSS 文件;
  3. 瀏覽器發出 CSS 文件的請求,服務器返回這個 CSS 文件;
  4. 瀏覽器繼續載入 html 中 <body> 部分的代碼,并且 CSS 文件已經拿到手了,可以開始渲染頁面了;
  5. 瀏覽器在代碼中發現一個 <img> 標簽引用了一張圖片,向服務器發出請求。此時瀏覽器不會等到圖片下載完,而是繼續渲染后面的代碼;
  6. 服務器返回圖片文件,由于圖片占用了一定面積,影響了后面段落的排布,因此瀏覽器需要回過頭來重新渲染這部分代碼;
  7. 瀏覽器發現了一個包含一行 JavaScript 代碼的 <script> 標簽,趕快運行它;
  8. JavaScript 腳本執行了這條語句,它命令瀏覽器隱藏掉代碼中的某個 <div> (style.display="none")。杯具啊,突然就少了這么一個元素,瀏覽器不得不重新渲染這部分代碼;
  9. 終于等到了 </html> 的到來,瀏覽器淚流滿面……
  10. 等等,還沒完,用戶點了一下界面中的“換膚”按鈕,JavaScript 讓瀏覽器換了一下 <link> 標簽的 CSS 路徑;
  11. 瀏覽器召集了在座的各位 <div><span><ul><li> 們,“大伙兒收拾收拾行李,咱得重新來過……”,瀏覽器向服務器請求了新的 CSS 文件,重新渲染頁面。

頁面為什么會慢?那是因為瀏覽器要花時間、花精力去渲染,尤其是當它發現某個部分發生了點變化影響了布局,需要倒回去重新渲染,我們稱這個回退的過程叫 reflow。

reflow 幾乎是無法避免的。現在常見的一些效果,比如樹狀目錄的折疊、展開(實質上是元素的顯示與隱藏)等,都將引起瀏覽器的 reflow。鼠標滑過、點擊等,只要這些行為引起了頁面上某些元素的占位面積、定位方式、邊距等屬性的變化,都會引起它內部、周圍甚至整個頁面的重新渲染。通常我們都無法預估瀏覽器到底會 reflow 哪一部分的代碼,它們都彼此相互影響著。

reflow

與 reflow 有個看上去差不多的術語叫 repaint (重繪),如果只是改變了某個元素的背景顏色,文字顏色等,不影響元素周圍或內部布局的屬性,將只會引起瀏覽器的 repaint,重畫某一部分。

repaint

2.4 引起 repaint 和 reflow 的一些操作

DOM Tree 里的每個結點都會有 reflow 方法,一個結點的 reflow 很有可能導致子結點,甚至父點以及同級結點的 reflow。在一些高性能的電腦上也許還沒什么,但是如果 reflow 發生在手機上,那么這個過程是非常痛苦和耗電的。

所以,下面這些動作有很大可能會是成本比較高的:

  • 當你增加、刪除、修改 DOM 結點時;
  • 當你移動 DOM 的位置,或是搞個動畫的時候;
  • 當你修改 CSS 樣式的時候;
  • 當你 Resize 窗口的時候(移動端沒有這個問題),或是滾動的時候;
  • 當你修改網頁的默認字體時;

注:display:none 會觸發 reflow,而 visibility:hidden 只會觸發 repaint,因為沒有發現位置變化。

2.5 reflow 優化

reflow 是不可避免的,只能將 reflow 對性能的影響減到最小,給出下面幾條建議:

1. 不要一條一條地修改 DOM 的樣式。與其這樣,還不如預先定義好 css 的 class,然后修改 DOM 的 className:

// 不好的寫法
var left = 10,
    top = 10;
elem.style.left = left + "px";
elem.style.top  = top  + "px";
// 推薦寫法
elem.className += " classname";

2. 把 DOM 離線后修改。如:

  • 使用 DocumentFragment 對象在內存里操作 DOM。
  • 先把 DOM 給 display:none (有一次 reflow),然后你想怎么改就怎么改。比如修改 100 次,然后再把他顯示出來。
  • clone 一個 DOM 節點到內存里,然后想怎么改就怎么改,改完后,和在線的那個的交換一下。

3. 不要把 DOM 節點的屬性值放在一個循環里當成循環里的變量。不然這會導致大量地讀寫這個結點的屬性。

4. 盡可能的修改層級比較低的 DOM節點。當然,改變層級比較低的 DOM節點有可能會造成大面積的 reflow,但是也可能影響范圍很小。

5. 為動畫的 HTML 元件使用 fixed 或 absoult 的 position,那么修改他們的 CSS 是會大大減小 reflow 。

6. 千萬不要使用 table 布局。因為可能很小的一個小改動會造成整個 table 的重新布局。

reflow 要比 repaint 更花費時間,因為 reflow 也會引發 repaint,也就更影響性能。所以在寫代碼的時候,要盡量避免過多的 reflow。

以上這些僅是對瀏覽器工作原理的一個簡單說明,大家如果對它感興趣,可以繼續搜索相關文章深入學習,因為我覺得理解瀏覽器的原理是很重要的,可以幫助我們寫出性能更好的頁面。

參考:

http://itrain.top/2016/11/javascript_how_broswers_work/

http://taligarsiel.com/Projects/howbrowserswork1.htm

https://segmentfault.com/a/1190000002629708

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,030評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,310評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,951評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,796評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,566評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,055評論 1 322
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,142評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,303評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,799評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,683評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,899評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,409評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,135評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,520評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,757評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,528評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,844評論 2 372

推薦閱讀更多精彩內容