者簡介:高揚,來自抖音社區安全前端團隊,團隊負責的工作重點在于降低社區中不良內容與行為對用戶造成的傷害。
觀察瀏覽器的任務管理器可以發現,打開瀏覽器的一個頁面需要多個進程,包括瀏覽器進程、GPU進程、網絡進程、渲染進程等,有插件的話還會包括各種插件進程(Chrome選項 -> 更多工具 -> 任務管理器)。
本文將聚焦于瀏覽器的各個進程間是如何配合,將頁面呈現給用戶的。
你將了解到
進程和線程
單進程和多進程瀏覽器
單進程瀏覽器
單進程瀏覽器是指所有功能模塊(網絡、插件、JS運行環境、渲染引擎、頁面等)都運行在同一進程中的瀏覽器(早期的IE、Firefox)。
單進程瀏覽器存在的問題:
多進程瀏覽器
Chrome一問世便使用了多進程的架構,其頁面運行在了單獨的渲染進程中,插件運行在單獨的插件進行中,進程間使用IPC進行通信。
瀏覽器的主要進程有哪些:
默認情況下,Chrome 會為每個 Tab 標簽創建一個渲染進程。因為渲染進程所有的內容都是通過網絡獲取的,會存在一些惡意代碼利用瀏覽器漏洞對系統進行攻擊,所以運行在渲染進程里面的代碼是不被信任的。這也是為什么 Chrome 會讓渲染進程運行在安全沙箱里,就是為了保證系統的安全。
其實,Chrome 剛開始發布的時候是沒有單獨 GPU 進程的,都是放到瀏覽器主進程中的。而 GPU 的使用初衷是為了實現 3D CSS 的效果,只是隨后網頁、Chrome 的 UI 界面都選擇采用 GPU 來繪制,這使得 GPU 成為瀏覽器普遍的需求。最后,Chrome 在其多進程架構上也引入了 GPU 進程。
多進程瀏覽器是如何解決單進程瀏覽的問題的:
多進程瀏覽器存在的問題:
從用戶發出URL請求到頁面開始解析的過程,叫做導航,是網絡加載流程和渲染流程之間的橋梁。
渲染流水線
渲染流水線可分為如下幾個子階段:構建 DOM 樹、樣式計算、布局、分層、繪制、分塊、光柵化和合成。
注意,并非布局樹的每個節點都包含一個圖層,一個節點可以直接或間接地屬于一個層,例如一個節點可以從屬于父節點的圖層
基于上述瀏覽器的渲染原理,我們可以理解回流和重繪是如何對瀏覽器性能造成影響的。由于瀏覽器渲染頁面默認使用流式布局模型,當某個DOM或CSS幾何屬性發生改變后,文檔流就會受到波動,就需要對DOM重新進行計算,重新布局頁面,引發回流。
[1] 瀏覽器工作原理與實踐:https://time.geekbang.org/column/intro/100033601
[2] 瀏覽器進程架構的演化:https://zhuanlan.zhihu.com/p/96957235
覽器渲染頁面有以下幾個步驟:
載網絡,侵權必刪
我們可能都知道瀏覽器含有一個渲染引擎,用來渲染窗口所展示的內容。默認情況下,渲染引擎可以顯示html、xml文檔及圖片,它也可以借助插件(一種瀏覽器擴展)顯示其他類型數據,例如使用PDF閱讀器插件,用于顯示PDF格式。但是其具體的渲染原理和流程估計也有很多人都不知道或者不清楚吧。這些天研究了一下瀏覽器的渲染原理,有了些心得,在這里跟大家分享一下,這里只討論渲染引擎最主要的用途——顯示應用了CSS之后的html及圖片。
渲染引擎簡介
本文所討論的瀏覽器——Firefox、Chrome和Safari是基于兩種渲染引擎構建的,Firefox使用Geoko——Mozilla自主研發的渲染引擎,Safari和Chrome都使用webkit。
渲染主流程
渲染引擎首先通過網絡獲得所請求文檔的內容,通常以8K分塊的方式完成。下面是渲染引擎在取得內容之后的基本流程:
解析html以構建dom樹 -> 構建render樹 -> 布局render樹 -> 繪制render樹
這里先解釋一下幾個概念,方便大家理解:
DOM Tree:瀏覽器將HTML解析成樹形的數據結構。
CSS Rule Tree:瀏覽器將CSS解析成樹形的數據結構。
Render Tree: DOM和CSSOM合并后生成Render Tree。
layout: 有了Render Tree,瀏覽器已經能知道網頁中有哪些節點、各個節點的CSS定義以及他們的從屬關系,從而去計算出每個節點在屏幕中的位置。
painting: 按照算出來的規則,通過顯卡,把內容畫到屏幕上。
reflow(回流):當瀏覽器發現某個部分發生了點變化影響了布局,需要倒回去重新渲染,內行稱這個回退的過程叫 reflow。reflow 會從 <html> 這個 root frame 開始遞歸往下,依次計算所有的結點幾何尺寸和位置。reflow 幾乎是無法避免的。現在界面上流行的一些效果,比如樹狀目錄的折疊、展開(實質上是元素的顯 示與隱藏)等,都將引起瀏覽器的 reflow。鼠標滑過、點擊……只要這些行為引起了頁面上某些元素的占位面積、定位方式、邊距等屬性的變化,都會引起它內部、周圍甚至整個頁面的重新渲 染。通常我們都無法預估瀏覽器到底會 reflow 哪一部分的代碼,它們都彼此相互影響著。
repaint(重繪):改變某個元素的背景色、文字顏色、邊框顏色等等不影響它周圍或內部布局的屬性時,屏幕的一部分要重畫,但是元素的幾何尺寸沒有變。
注意:(1)display:none 的節點不會被加入Render Tree,而visibility: hidden 則會,所以,如果某個節點最開始是不顯示的,設為display:none是更優的。
(2)display:none 會觸發 reflow,而 visibility:hidden 只會觸發 repaint,因為沒有發現位置變化。
(3)有些情況下,比如修改了元素的樣式,瀏覽器并不會立刻reflow 或 repaint 一次,而是會把這樣的操作積攢一批,然后做一次 reflow,這又叫異步 reflow 或增量異步 reflow。但是在有些情況下,比如resize 窗口,改變了頁面默認的字體等。對于這些操作,瀏覽器會馬上進行 reflow。
來看看webkit的主要流程:
再來看看Geoko的主要流程:
Gecko 里把格式化好的可視元素稱做“幀樹”(Frame tree)。每個元素就是一個幀(frame)。 webkit 則使用”渲染樹”這個術語,渲染樹由”渲染對象”組成。webkit 里使用”layout”表示元素的布局,Gecko則稱為”reflow”。Webkit使用”Attachment”來連接DOM節點與可視化信息以構建渲染樹。一個非語義上的小差別是Gecko在HTML與DOM樹之間有一個附加的層 ,稱作”content sink”,是創建DOM對象的工廠。
盡管Webkit與Gecko使用略微不同的術語,這個過程還是基本相同的,如下:
1. 瀏覽器會將HTML解析成一個DOM樹,DOM 樹的構建過程是一個深度遍歷過程:當前節點的所有子節點都構建好后才會去構建當前節點的下一個兄弟節點。
2. 將CSS解析成 CSS Rule Tree 。
3. 根據DOM樹和CSSOM來構造 Rendering Tree。注意:Rendering Tree 渲染樹并不等同于 DOM 樹,因為一些像Header或display:none的東西就沒必要放在渲染樹中了。
4. 有了Render Tree,瀏覽器已經能知道網頁中有哪些節點、各個節點的CSS定義以及他們的從屬關系。下一步操作稱之為layout,顧名思義就是計算出每個節點在屏幕中的位置。
5. 再下一步就是繪制,即遍歷render樹,并使用UI后端層繪制每個節點。
注意:上述這個過程是逐步完成的,為了更好的用戶體驗,渲染引擎將會盡可能早的將內容呈現到屏幕上,并不會等到所有的html都解析完成之后再去構建和布局render樹。它是解析完一部分內容就顯示一部分內容,同時,可能還在通過網絡下載其余內容。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。