參考文章:不同內(nèi)核瀏覽器的差異以及瀏覽器渲染簡(jiǎn)介 ,并根據(jù)目前瀏覽器發(fā)展情況進(jìn)行了修改。
一、常見瀏覽器及其內(nèi)核
| Web Browser | ![]() Chrome
|
![]() IE
|
![]() FireFox
|
![]() Safari
|
![]() Opera
|
|---|---|---|---|---|---|
| Rendering Engine | Webkit-Blink | Trident | Gecko | Webkit | Presto/Blink |
微軟的新一代瀏覽器Microsoft Edge,宣布打算采用Chromium開源項(xiàng)目開發(fā)桌面版的Microsoft Edge瀏覽器,詳情見Microsoft Edge: Making the web better through more open source collaboration.
對(duì)此 個(gè)人表示喜大普奔,畢竟IE太難用了,開發(fā)的時(shí)候做兼容也是非常惡心,但是起碼在5年內(nèi),IE兼容還是要寫的啊(╥╯^╰╥)
二、什么是內(nèi)核
瀏覽器最重要或者說核心的部分是“Rendering Engine”,可大概譯為“解釋引擎”,不過我們一般習(xí)慣將之稱為“瀏覽器內(nèi)核”。負(fù)責(zé)對(duì)網(wǎng)頁語法的解釋(如HTML、JavaScript)并渲染(顯示)網(wǎng)頁。
所以,通常所謂的瀏覽器內(nèi)核也就是瀏覽器所采用的渲染引擎,渲染引擎決定了瀏覽器如何顯示網(wǎng)頁的內(nèi)容以及頁面的格式信息。
不同的瀏覽器內(nèi)核對(duì)網(wǎng)頁編寫語法的解釋也有不同,因此同一網(wǎng)頁在不同的內(nèi)核的瀏覽器里的渲染(顯示)效果也可能不同,這也是網(wǎng)頁編寫者需要在不同內(nèi)核的瀏覽器中測(cè)試網(wǎng)頁顯示效果的原因。
另一種關(guān)于內(nèi)核的說明:維基百科(↓)
一、 排版引擎
排版引擎(layout engine),也稱為瀏覽器引擎(web browser engine)、頁面渲染引擎(rendering engine)或樣版引擎,它是一種軟件組件,負(fù)責(zé)獲取標(biāo)記式內(nèi)容(如HTML、XML及圖像文件等等)、整理信息(如CSS及XSL等),并將排版后的內(nèi)容輸出至顯示器或打印機(jī)。
二、JavaScript引擎
顧名思義,JavaScript引擎就是用來渲染JavaScript的。
JavaScript引擎是一個(gè)專門處理JavaScript腳本的虛擬機(jī),一般會(huì)附帶在網(wǎng)頁瀏覽器之中。
| JS引擎 | 應(yīng)用程序(實(shí)現(xiàn)) |
|---|---|
| V8 | Google Chrome |
| SpiderMonkey | Mozilla Firefox |
| JavaScriptCore | Safari |
| Chakra (JScript引擎) | Internet Explorer |
| Chakra (JavaScript引擎) | Microsoft Edge |
| KJS | Konqueror |
三、瀏覽器渲染原理
Web頁面運(yùn)行在各種各樣的瀏覽器當(dāng)中,瀏覽器載入、渲染頁面的速度直接影響著用戶體驗(yàn)簡(jiǎn)單地說,頁面渲染就是瀏覽器將html代碼根據(jù)CSS定義的規(guī)則顯示在瀏覽器窗口中的這個(gè)過程。
先來大致了解一下瀏覽器都是怎么干活的:
用戶輸入網(wǎng)址(假設(shè)是個(gè)html頁面,并且是第一次訪問),瀏覽器向服務(wù)器發(fā)出請(qǐng)求,服務(wù)器返回html文件;
瀏覽器開始載入html代碼,發(fā)現(xiàn)<head>標(biāo)簽內(nèi)有一個(gè)<link>標(biāo)簽引用外部CSS文件;
瀏覽器又發(fā)出CSS文件的請(qǐng)求,服務(wù)器返回這個(gè)CSS文件;
瀏覽器繼續(xù)載入html中<body>部分的代碼,并且CSS文件已經(jīng)拿到手了,可以開始渲染頁面了;
瀏覽器在代碼中發(fā)現(xiàn)一個(gè)<img>標(biāo)簽引用了一張圖片,向服務(wù)器發(fā)出請(qǐng)求。此時(shí)瀏覽器不會(huì)等到圖片下載完,而是繼續(xù)渲染后面的代碼;
服務(wù)器返回圖片文件,由于圖片占用了一定面積,影響了后面段落的排布,因此瀏覽器需要回過頭來重新渲染這部分代碼;
瀏覽器發(fā)現(xiàn)了一個(gè)包含一行Javascript代碼的<script>標(biāo)簽,趕快運(yùn)行它;
Javascript腳本執(zhí)行了這條語句,它命令瀏覽器隱藏掉代碼中的某個(gè)(style.display=”none”)。杯具啊,突然就少了這么一個(gè)元素,瀏覽器不得不重新渲染這部分代碼;
終于等到了</html>的到來,瀏覽器淚流滿面……
等等,還沒完,用戶點(diǎn)了一下界面中的“換膚”按鈕,Javascript讓瀏覽器換了一下<link>標(biāo)簽的CSS路徑;
瀏覽器召集了在座的各位
<span><ul><li>們,“大伙兒收拾收拾行李,咱得重新來過……”,瀏覽器向服務(wù)器請(qǐng)求了新的CSS文件,重新渲染頁面。
說到頁面為什么會(huì)慢?那是因?yàn)闉g覽器要花時(shí)間、花精力去渲染,尤其是當(dāng)它發(fā)現(xiàn)某個(gè)部分發(fā)生了點(diǎn)變化影響了布局,需要倒回去重新渲染,內(nèi)行稱這個(gè)回退的過程叫reflow。

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

reflow問題是可以優(yōu)化的,我們可以盡量減少不必要的reflow。
比如開頭的例子中的<img>圖片載入問題,這其實(shí)就是一個(gè)可以避免的reflow——給圖片設(shè)置寬度和高度就可以了。
這樣瀏覽器就知道了圖片的占位面積,在載入圖片前就預(yù)留好了位置。
另外,有個(gè)和reflow看上去差不多的術(shù)語:repaint,中文叫重繪。
如果只是改變某個(gè)元素的背景色、文字顏色、邊框顏色等等不影響它周圍或內(nèi)部布局的屬性,將只會(huì)引起瀏覽器repaint。
repaint的速度明顯快于 reflow(在IE下需要換一下說法,reflow要比repaint 更緩慢) 霧 。
四、從瀏覽器的渲染原理講CSS性能
我們主要根據(jù)瀏覽器的渲染原理對(duì)CSS的書寫性能做一點(diǎn)改進(jìn)(當(dāng)然還有JS本篇文章暫不考慮,后面的文章會(huì)做介紹),下面讓我們一起來揭開瀏覽器的渲染原理這一神秘的面紗吧:
最終決定瀏覽器表現(xiàn)出來的頁面效果的差異是:渲染引擎 Rendering Engine(也叫做排版引擎),也就是我們通常所說的“瀏覽器內(nèi)核”,負(fù)責(zé)解析網(wǎng)頁語法(如HTML、JavaScript)并渲染、展示網(wǎng)頁。相同的代碼在不同的瀏覽器呈現(xiàn)出來的效果不一樣,那么就很有可能是不同的瀏覽器內(nèi)核導(dǎo)致的。
我們來看一下加載頁面時(shí)瀏覽器的具體工作流程:
1、解析HTML以重建DOM樹(Parsing HTML to construct the DOM tree ):
渲染引擎開始解析HTML文檔,轉(zhuǎn)換樹中的標(biāo)簽到DOM節(jié)點(diǎn),它被稱為“內(nèi)容樹”。
2、構(gòu)建渲染樹(Render tree construction):
解析CSS(包括外部CSS文件和樣式元素),根據(jù)CSS選擇器計(jì)算出節(jié)點(diǎn)的樣式,創(chuàng)建另一個(gè)樹 —- 渲染樹。
3、布局渲染樹(Layout of the render tree):
<wbr style="font-family: "Microsoft Yahei", sans-serif;">從根節(jié)點(diǎn)遞歸調(diào)用,計(jì)算每一個(gè)元素的大小、位置等,給每個(gè)節(jié)點(diǎn)所應(yīng)該出現(xiàn)在屏幕上的精確坐標(biāo)。
4、繪制渲染樹(Painting the render tree)
<wbr style="font-family: "Microsoft Yahei", sans-serif;">: 遍歷渲染樹,每個(gè)節(jié)點(diǎn)將使用UI后端層來繪制。
主要的流程就是:構(gòu)建一個(gè)dom樹,頁面要顯示的各元素都會(huì)創(chuàng)建到這個(gè)dom樹當(dāng)中,每當(dāng)一個(gè)新元素加入到這個(gè)dom樹當(dāng)中,瀏覽器便會(huì)通過css引擎查遍css樣式表,找到符合該元素的樣式規(guī)則應(yīng)用到這個(gè)元素上。
注意了:css引擎查找樣式表,對(duì)每條規(guī)則都按從右到左的順序去匹配。
對(duì)此,在CSS書寫過程中,總結(jié)出如下性能提升的方案:
- 避免使用通配規(guī)則 如 *{} 計(jì)算次數(shù)驚人!只對(duì)需要用到的元素進(jìn)行選擇
- 盡量少的去對(duì)標(biāo)簽進(jìn)行選擇,而是用class 如:#nav li{},可以為li加上nav_item的類名,如下選擇.nav_item{}
- 不要去用標(biāo)簽限定ID或者類選擇符 如:ul#nav,應(yīng)該簡(jiǎn)化為#nav
- 盡量少的去使用后代選擇器,降低選擇器的權(quán)重值 后代選擇器的開銷是最高的,盡量將選擇器的深度降到最低,最高不要超過三層,更多的使用類來關(guān)聯(lián)每一個(gè)標(biāo)簽元素
- 考慮繼承 了解哪些屬性是可以通過繼承而來的,然后避免對(duì)這些屬性重復(fù)指定規(guī)則




