瀏覽器的主要構(gòu)成
1.用戶界面
2.瀏覽器引擎 - 用來查詢及操作渲染引擎的接口
3.渲染引擎 - 用來顯示請求的內(nèi)容
4.網(wǎng)絡(luò) - 完成網(wǎng)絡(luò)調(diào)用
5.UI后端 - 繪制基本的組件,具有通用接口,底層調(diào)用操作系統(tǒng)的用戶接口
6.JS解釋器
7.數(shù)據(jù)存儲 - 屬于持久層座慰,瀏覽器需要在硬盤中保存類似cookie的各種數(shù)據(jù)屏积,HTML5定義了web database技術(shù)蒸甜,這是一種輕量級完整的客戶端存儲技術(shù)
這里主要討論渲染引擎
Geoko
引擎是由Mozilla自主研發(fā)的渲染引擎却嗡,F(xiàn)irefox瀏覽器是基于此引擎構(gòu)建的闰渔;
webkit
是一款開源渲染引擎暮现,Safari和Chrome都使用webkit还绘。相關(guān)內(nèi)容請參考http://webkit.org
渲染的主流程
渲染引擎首先通過網(wǎng)絡(luò)獲得所請求文檔的內(nèi)容,通常以8K分塊的方式完成栖袋。
下面是渲染引擎在取得內(nèi)容之后的基本流程:
解析html以構(gòu)建dom樹 -> 構(gòu)建render樹 -> 布局render樹 -> 繪制render樹
這里的幾個概念:
DOM Tree:瀏覽器將HTML解析成樹形的數(shù)據(jù)結(jié)構(gòu)拍顷。
CSS Rule Tree:瀏覽器將CSS解析成樹形的數(shù)據(jù)結(jié)構(gòu)。
Render Tree: DOM和CSSOM合并后生成Render Tree栋荸。
layout: 有了Render Tree菇怀,瀏覽器已經(jīng)能知道網(wǎng)頁中有哪些節(jié)點(diǎn)、各個節(jié)點(diǎn)的CSS定義以及他們的從屬關(guān)系晌块,從而去計(jì)算出每個節(jié)點(diǎn)在屏幕中的位置
painting: 按照算出來的規(guī)則爱沟,通過顯卡,把內(nèi)容畫到屏幕上匆背。
瀏覽器在服務(wù)器拿到數(shù)據(jù)后呼伸,會解析HTML,CSS以及js文件钝尸,形成DOM tree括享,CSS rule tree,并通過js操作它們珍促。
解析完成后铃辖,瀏覽器引擎通過DOM tree,CSS rule tree 構(gòu)建rendering tree猪叙。
css rule tree主要完成匹配娇斩,并把css rule賦給rendering tree的每個元素。
需要注意的是穴翩,rendering tree和DOM tree并不是完全一一對應(yīng)的犬第。不可見的DOM元素,是不會插入渲染數(shù)的芒帕。例如head元素歉嗓,又如display:none的元素。(visibility:hidden 會出現(xiàn)在渲染樹當(dāng)中)
渲染樹構(gòu)建完成后背蟆,瀏覽器會
1.對這些元素進(jìn)行定位和布局鉴分,這一步也叫做reflow或者layout哮幢。
2.繪制這些元素的樣式,顏色冠场,背景家浇,大小及邊框等,這一步也叫做repaint碴裙。
3.將各層的信息發(fā)送給GPU,GPU會將各層合成点额;顯示在屏幕上舔株。
reflow和layout做的事情基本相同,只是不同的渲染引擎的流程術(shù)語不同还棱,webkit中元素的定位稱為layout载慈,Gecko中稱為reflow。
reflow和repaint都是消耗瀏覽器性能的操作珍手,簡直說明一下
reflow(回流): 當(dāng)瀏覽器發(fā)現(xiàn)某個部分發(fā)生了點(diǎn)變化影響了布局办铡,需要倒回去重新渲染,這個回退的過程叫 reflow琳要。reflow 會從 <html> 這個 root frame 開始遞歸往下寡具,依次計(jì)算所有的結(jié)點(diǎn)幾何尺寸和位置。
repaint(重繪): 改變元素的背景色稚补,文字色童叠,邊框色等等不影響布局的屬性時,屏幕需要重畫但是元素的尺寸和位置沒有變课幕。
在reflow和repaint結(jié)束后厦坛,瀏覽器會將復(fù)合層傳入GPU進(jìn)行合成展示在屏幕上。
有些時候乍惊,動畫不夠流暢杜秸,主要就是因?yàn)檫M(jìn)行了太多的reflow和repaint。例如
<style>
#a, #b {
position: absolute;
}
#a {
left: 10px;
top: 10px;
z-index: 2;
animation: move 1s linear;
}
#b {
left: 50px;
top: 50px;
z-index: 1;
}
@keyframes move {
from { left: 30px; }
to { left: 100px; }
}
</style>
<div id="#a">A</div>
<div id="#b">B</div>
在這個例子中润绎,對于動畫的每一幀撬碟;瀏覽器會計(jì)算元素的幾何形狀,渲染新狀態(tài)的圖像凡橱;并把它們發(fā)送給GPU小作。(你沒看錯,position也會引起瀏覽器重排的)盡管瀏覽器做了優(yōu)化稼钩,在repaint時顾稀,只會repaint部分區(qū)域;但是我們的動畫仍然不夠流暢坝撑。
因?yàn)橹嘏藕椭乩L發(fā)生在動畫的每一幀静秆,一個有效避免reflow和repaint的方式是我們僅僅畫兩個圖像粮揉;一個是a元素,一個是b元素及整個頁面抚笔;我們將這兩張圖片發(fā)送給GPU扶认,然后動畫發(fā)生的時候;只做兩張圖片相對對方的平移殊橙。也就是說辐宾,僅僅合成緩存的圖片將會很快;這也是GPU的優(yōu)勢——它能非撑蚵快地以亞像素精度地合成圖片叠纹,并給動畫帶來平滑的曲線。
為了僅發(fā)生composite敞葛,我們做動畫的css property必須滿足以下三個條件:
1.不影響文檔流
2.不依賴文檔流
3.不會造成重繪
滿足以上以上條件的css property只有transform和opacity誉察。你可能以為position也滿足以上條件,但事實(shí)不是這樣惹谐,舉個例子left屬性可以使用百分比的值持偏,依賴于它的offset parent。還有em氨肌、vh等其他單位也依賴于他們的環(huán)境鸿秆。
我們使用translate來代替left
<style>
#a, #b {
position: absolute;
}
#a {
left: 10px;
top: 10px;
z-index: 2;
animation: move 1s linear;
}
#b {
left: 50px;
top: 50px;
z-index: 1;
}
@keyframes move {
from { transform: translateX(0); }
to { transform: translateX(70px); }
}
</style>
<div id="#a">A</div>
<div id="#b">B</div>
瀏覽器在動畫執(zhí)行之前就知道動畫如何開始和結(jié)束,因?yàn)闉g覽器沒有看到需要reflow和repaint的操作儒飒;瀏覽器就會畫兩張圖像作為復(fù)合層谬莹,并將它們傳入GPU。
參考:
http://blog.jobbole.com/12749/
https://segmentfault.com/a/1190000008015671