新聞中心
大家好,我是 CUGGZ。

發(fā)展壯大離不開廣大客戶長期以來的信賴與支持,我們將始終秉承“誠信為本、服務(wù)至上”的服務(wù)理念,堅持“二合一”的優(yōu)良服務(wù)模式,真誠服務(wù)每家企業(yè),認真做好每個細節(jié),不斷完善自我,成就企業(yè),實現(xiàn)共贏。行業(yè)涉及石牌坊等,在網(wǎng)站建設(shè)公司、營銷型網(wǎng)站、WAP手機網(wǎng)站、VI設(shè)計、軟件開發(fā)等項目上具有豐富的設(shè)計經(jīng)驗。
今天來分享一下瀏覽器的渲染原理及流程。
前言
先來看看 Chrome 瀏覽器的多進程架構(gòu):
通常,我們打包出來的 HTML、CSS、JavaScript 等文件,經(jīng)過瀏覽器運行之后就會顯示出頁面,這個過程就是瀏覽器的渲染進程來操作實現(xiàn)的,渲染進程的主要任務(wù)就是將靜態(tài)資源轉(zhuǎn)化為可視化界面:
對于中間的瀏覽器,它就是一個黑盒,下面就來看看這個黑盒是如何將靜態(tài)資源轉(zhuǎn)化為前端界面的。由于渲染機制比較復(fù)雜,所以渲染模塊在執(zhí)行過程中會被劃分為很多子階段,輸入的靜態(tài)資源經(jīng)過這些子階段,最后輸出頁面。我們將一個處理流程稱為渲染流水線,其大致流程如下圖所示:
這里主要包含五個過程:
- DOM樹構(gòu)建:渲染引擎使用HTML解析器(調(diào)用XML解析器)解析HTML文檔,將各個HTML元素逐個轉(zhuǎn)化成DOM節(jié)點,從而生成DOM樹。
- CSSOM樹構(gòu)建:CSS解析器解析CSS,并將其轉(zhuǎn)化為CSS對象,將這些CSS對象組裝起來,構(gòu)建CSSOM樹。
- 渲染樹構(gòu)建:DOM 樹和 CSSOM 樹都構(gòu)建完成以后,瀏覽器會根據(jù)這兩棵樹構(gòu)建出一棵渲染樹。
- 頁面布局:渲染樹構(gòu)建完畢之后,元素的位置關(guān)系以及需要應(yīng)用的樣式就確定了,這時瀏覽器會計算出所有元素的大小和絕對位置。
- 頁面繪制:頁面布局完成之后,瀏覽器會將根據(jù)處理出來的結(jié)果,把每一個頁面圖層轉(zhuǎn)換為像素,并對所有的媒體文件進行解碼。
對于這五個流程,每一階段都有對應(yīng)的產(chǎn)物:DOM樹、CSSOM樹、渲染樹、盒模型、界面。
下圖為渲染引擎工作流程中各個步驟所對應(yīng)的模塊:
從圖中可以看出,渲染引擎主要包含的模塊有:
- HTML 解析器:解析HTML文檔,主要作用是將HTML文檔轉(zhuǎn)換成DOM樹。
- CSS 解析器:將DOM中的各個元素對象進行計算,獲取樣式信息,用于渲染樹的構(gòu)建。
- JavaScript 解釋器:使用JavaScript可以修改網(wǎng)頁的內(nèi)容、CSS規(guī)則等。JavaScript解釋器能夠解釋JavaScript代碼,并通過DOM接口和CSSOM接口來修改網(wǎng)頁內(nèi)容、樣式規(guī)則,從而改變渲染結(jié)果。
- 頁面布局:DOM創(chuàng)建之后,渲染引擎將其中的元素對象與樣式規(guī)則進行結(jié)合,可以得到渲染樹。布局則是針對渲染樹,計算其各個元素的大小、位置等布局信息。
- 頁面繪制:使用圖形庫將布局計算后的渲染樹繪制成可視化的圖像結(jié)果。
DOM樹構(gòu)建
在說構(gòu)建DOM樹之前,我們需要知道,為什么要構(gòu)建DOM樹呢? 這是因為,瀏覽器無法直接理解和使用 HTML,所以需要將HTML轉(zhuǎn)化為瀏覽器能夠理解的結(jié)構(gòu)——DOM樹。
了解過數(shù)據(jù)結(jié)構(gòu)的小伙伴對于樹結(jié)構(gòu)應(yīng)該不陌生,樹是由結(jié)點或頂點和邊組成的且不存在著任何環(huán)的一種數(shù)據(jù)結(jié)構(gòu)。一棵非空的樹包括一個根結(jié)點,還有多個附加結(jié)點,所有結(jié)點構(gòu)成一個多級分層結(jié)構(gòu)。下面通過一張圖來看看什么是樹結(jié)構(gòu):
對于上面的三個結(jié)構(gòu),前兩個都是樹,他們都只有唯一的根節(jié)點,而且不存在環(huán)結(jié)構(gòu)。而第三個存在環(huán),所以就不是一個樹結(jié)構(gòu)。
在頁面中,每個HTML標簽都會被瀏覽器解析成文檔對象。HTML本質(zhì)上就是一個嵌套結(jié)構(gòu),在解析時會把每個文檔對象用一個樹形結(jié)構(gòu)組織起來,所有的文檔對象都會掛在document上,這種組織方式就是HTML最基礎(chǔ)的結(jié)構(gòu)——文檔對象模型(DOM),這棵樹的每個文檔對象就叫做DOM節(jié)點。
在渲染引擎中,DOM 有三個層面的作用:
- 從頁面的視角來看,DOM 是生成頁面的基礎(chǔ)數(shù)據(jù)結(jié)構(gòu)。
- 從 JavaScript 腳本視角來看,DOM 提供給 JavaScript 腳本操作的接口,通過這套接口,JavaScript 可以對 DOM 結(jié)構(gòu)進行訪問,從而改變文檔的結(jié)構(gòu)、樣式和內(nèi)容。
- 從安全視角來看,DOM 是一道安全防護線,一些不安全的內(nèi)容在 DOM 解析階段會被拒之門外。
在渲染引擎內(nèi)部,HTML 解析器負責(zé)將 HTML 字節(jié)流轉(zhuǎn)換為 DOM 結(jié)構(gòu),其轉(zhuǎn)化過程如下:
1、字符流 → 詞(token)
HTML結(jié)構(gòu)會首先通過分詞器將字節(jié)流拆分為詞(token)。Token分為Tag Token 和文本 Token。下面來看一個HTML代碼是如何被拆分的:
hello world
對于這段代碼,可以拆成詞:
可以看到,Tag Token 又分 StartTag 和 EndTag,
、?就是 StartTag ,、
這里會通過狀態(tài)機將字符拆分成token,所謂的狀態(tài)機就是將每個詞的特征逐個拆分成獨立的狀態(tài),然后再將所有詞的特征字符合并起來,形成一個連通的圖結(jié)構(gòu)。那為什么要使用狀態(tài)機呢?因為每讀取一個字符,都要做一次決策,這些決策都和當(dāng)前的狀態(tài)有關(guān)。
實際上,狀態(tài)機的作用就是用來做詞法分析的,將字符流分解為詞(token)。
2、詞(token)→ DOM樹
接下來就需要將 Token 解析為 DOM 節(jié)點,并將 DOM 節(jié)點添加到 DOM 樹中。這個過程是通過棧結(jié)構(gòu)來實現(xiàn)的,這個棧主要用來計算節(jié)點之間的父子關(guān)系,上面步驟中生成的token會按順序壓入棧中,該過程的規(guī)則如下:
- 如果分詞器解析出來是StartTag Token,HTML 解析器會為該 Token 創(chuàng)建一個 DOM 節(jié)點,然后將該節(jié)點加入到 DOM 樹中,它的父節(jié)點就是棧中相鄰的那個元素生成的節(jié)點。
- 如果分詞器解析出來是文本Token,那么會生成一個文本節(jié)點,然后將該節(jié)點加入到 DOM 樹中,文本 Token 是不需要壓入到棧中,它的父節(jié)點就是當(dāng)前棧頂 Token 所對應(yīng)的 DOM 節(jié)點。
- 如果分詞器解析出來的是EndTag Token,比如是 EndTag div,HTML 解析器會查看 Token 棧頂?shù)脑厥欠袷?StarTag div,如果是,就將 StartTag div從棧中彈出,表示該 div 元素解析完成。
通過分詞器產(chǎn)生的新 Token 就這樣不停地入棧和出棧,整個解析過程就這樣一直持續(xù)下去,直到分詞器將所有字節(jié)流分詞完成。
下面來看看這的Token棧是如何工作的,有如下HTML結(jié)構(gòu):
hello juejin
hello world
開始時,HTML解析器會創(chuàng)建一個根為 document 的空的 DOM 結(jié)構(gòu),同時將 StartTag document 的Token壓入棧中,然后再將解析出來的第一個 StartTag html 壓入棧中,并創(chuàng)建一個 html 的DOM節(jié)點,添加到 document 上,這時 Token 棧和 DOM樹 如下:
接下來body和div標簽也會和上面的過程一樣,進行入棧操作:
隨后就會解析到 div標簽中的文本Token,渲染引擎會為該 Token 創(chuàng)建一個文本節(jié)點,并將該 Token 添加到 DOM 中,它的父節(jié)點就是當(dāng)前 Token 棧頂元素對應(yīng)的節(jié)點:
接下來就是第一個EndTag div,這時 HTML 解析器會判斷當(dāng)前棧頂元素是否是 StartTag div,如果是,則從棧頂彈出 StartTag div,如下圖所示:
再之后的過程就和上面類似了,最終的結(jié)果如下:
CSSOM樹構(gòu)建
上面已經(jīng)基本了解了DOM的構(gòu)建過程,但是這個DOM結(jié)構(gòu)只包含節(jié)點,并不包含任何的樣式信息。下面就來看看,瀏覽器是如何把CSS樣式應(yīng)用到DOM節(jié)點上的。
同樣,瀏覽器也是無法直接理解CSS代碼的,需要將其瀏覽器可以理解的CSSOM樹。實際上。瀏覽器在構(gòu)建 DOM 樹的同時,如果樣式也加載完成了,那么 CSSOM 樹也會同步構(gòu)建。CSSOM 樹和 DOM 樹類似,它主要有兩個作用:
- 提供給 JavaScript 操作樣式的能力。
- 為渲染樹的合成提供基礎(chǔ)的樣式信息。
不過,CSSOM 樹和 DOM 樹是獨立的兩個數(shù)據(jù)結(jié)構(gòu),它們并沒有一一對應(yīng)關(guān)系。DOM 樹描述的是 HTML 標簽的層級關(guān)系,CSSOM 樹描述的是選擇器之間的層級關(guān)系??梢栽跒g覽器的控制臺,通過document.styleSheets命令來查看CSSOM樹:
那CSS樣式的來源有哪些呢?
CSS樣式的來源主要有三種:
- 通過 link 引用的外部 CSS 樣式文件。
CUGGZ
hello world


咨詢
建站咨詢