不同浏览器内核
?
??在寫(xiě)前端的時(shí)候,了解了一些瀏覽器兼容的問(wèn)題,印象最深的還是圓角和漸變(感謝千年弦歌)。
? 瀏覽器最重要或者說(shuō)核心的部分是“Rendering Engine”,我們一般稱之為“瀏覽器內(nèi)核”。? 它負(fù)責(zé)對(duì)網(wǎng)頁(yè)語(yǔ)法的解釋(如HTML、JavaScript)并渲染(顯示)網(wǎng)頁(yè)。
? 相同的代碼在不同的瀏覽器呈現(xiàn)出來(lái)的效果不一樣,那么就很有可能是不同的瀏覽器內(nèi)核導(dǎo)致的。
? 那么問(wèn)題來(lái)了?——
?
一、整理一下主流瀏覽器的內(nèi)核:
Trident(windows)——IE
? 其他:世界之窗,360安全瀏覽器, 遨游2.0(3.0以上版本開(kāi)始采用webkit內(nèi)核),搜狗瀏覽器,騰訊TT
? trident直譯是三叉的(還是美國(guó)一個(gè)口香糖牌子,什么鬼跑偏了)
Gecko(跨平臺(tái))——FireFox????直譯是壁虎,gecko是Netscape6開(kāi)始采用的內(nèi)核,后來(lái)的Mozilla FireFox (火狐瀏覽器) 也采用了該內(nèi)核,Gecko的特點(diǎn)是代碼完全公開(kāi),因此,其可開(kāi)發(fā)程度很高,全世界的程序員都可以為其編寫(xiě)代碼,增加功能。
因?yàn)檫@是個(gè)開(kāi)源內(nèi)核,因此受到許多人的青睞,Gecko內(nèi)核的瀏覽器也很多,這也是Geckos內(nèi)核雖然年輕但市場(chǎng)占有率能夠迅速提高的重要原因。
Presto——Opera前內(nèi)核==
??presto直譯是急板的,說(shuō)變就變的。該內(nèi)核在2003年的Opera7中首次被使用,該款引擎的特點(diǎn)就是渲染速度的優(yōu)化達(dá)到了極致,也是之前公認(rèn)網(wǎng)頁(yè)瀏覽速度最快的瀏覽器內(nèi)核,然而代價(jià)是犧牲了網(wǎng)頁(yè)的兼容性。
Webkit——蘋(píng)果的safari(win/mac/iphone/ipad) 、google的chrome、opera(2015轉(zhuǎn)webkit)、塞班手機(jī)瀏覽器、Android手機(jī)默認(rèn)的瀏覽器、搜狗瀏覽器、QQ瀏覽器
? 蘋(píng)果公司自己的內(nèi)核,也是蘋(píng)果的Safari瀏覽器使用的內(nèi)核。
其中基于webkit的chromium內(nèi)核的有——搜狗瀏覽器、QQ瀏覽器、chrome、360、opera(這個(gè)內(nèi)核現(xiàn)在才是最快的)
知乎上看到一句話:Chromium不是靠采用WebKit贏的,是靠它在WebKit基礎(chǔ)上做出了自己的特色而贏的。
?
然而,現(xiàn)在國(guó)內(nèi)很多瀏覽器都采用了雙核,例如360極速/安全瀏覽器、獵豹瀏覽器、遨游瀏覽器、搜狗瀏覽器。
國(guó)產(chǎn)雙核瀏覽器都有兩個(gè)核,分別是IE兼容內(nèi)核(也叫兼容模式)和基于Chromium開(kāi)發(fā)的極速內(nèi)核(也叫極速模式或高速模式)。
簡(jiǎn)單來(lái)說(shuō),基于Chromium內(nèi)核的極速模式上網(wǎng)速度會(huì)更快,并且支持各種瀏覽器擴(kuò)展插件(也就是添加各種你想要的功能),唯一的缺陷就是不支持國(guó)內(nèi)某些不更新的網(wǎng)站(例如政府和部分銀行的)。一般情況下使用極速模式來(lái)上網(wǎng)就對(duì)了,當(dāng)發(fā)現(xiàn)網(wǎng)頁(yè)顯示不正常時(shí),再手動(dòng)切換到IE兼容模式就行。
一般切換方式:在地址欄上點(diǎn)一下“IE圖標(biāo)”或者“閃電圖標(biāo)”就能切換到另一個(gè)內(nèi)核。
?
二、瀏覽器渲染原理Web頁(yè)面運(yùn)行在各種各樣的瀏覽器當(dāng)中,瀏覽器載入、渲染頁(yè)面的速度直接影響著用戶體驗(yàn)簡(jiǎn)單地說(shuō),頁(yè)面渲染就是瀏覽器將html代碼根據(jù)CSS定義的規(guī)則顯示在瀏覽器窗口中的這個(gè)過(guò)程。先來(lái)大致了解一下瀏覽器都是怎么干活的:
1. 用戶輸入網(wǎng)址(假設(shè)是個(gè)html頁(yè)面,并且是第一次訪問(wèn)),瀏覽器向服務(wù)器發(fā)出請(qǐng)求,服務(wù)器返回html文件;
2. 瀏覽器開(kāi)始載入html代碼,發(fā)現(xiàn)<head>標(biāo)簽內(nèi)有一個(gè)<link>標(biāo)簽引用外部CSS文件;
3. 瀏覽器又發(fā)出CSS文件的請(qǐng)求,服務(wù)器返回這個(gè)CSS文件;
4. 瀏覽器繼續(xù)載入html中<body>部分的代碼,并且CSS文件已經(jīng)拿到手了,可以開(kāi)始渲染頁(yè)面了;
5. 瀏覽器在代碼中發(fā)現(xiàn)一個(gè)<img>標(biāo)簽引用了一張圖片,向服務(wù)器發(fā)出請(qǐng)求。此時(shí)瀏覽器不會(huì)等到圖片下載完,而是繼續(xù)渲染后面的代碼;
6. 服務(wù)器返回圖片文件,由于圖片占用了一定面積,影響了后面段落的排布,因此瀏覽器需要回過(guò)頭來(lái)重新渲染這部分代碼;
7. 瀏覽器發(fā)現(xiàn)了一個(gè)包含一行Javascript代碼的<script>標(biāo)簽,趕快運(yùn)行它;
8. Javascript腳本執(zhí)行了這條語(yǔ)句,它命令瀏覽器隱藏掉代碼中的某個(gè)
(style.display=”none”)。杯具啊,突然就少了這么一個(gè)元素,瀏覽器不得不重新渲染這部分代碼; 9. 終于等到了</html>的到來(lái),瀏覽器淚流滿面…… 10. 等等,還沒(méi)完,用戶點(diǎn)了一下界面中的“換膚”按鈕,Javascript讓瀏覽器換了一下<link>標(biāo)簽的CSS路徑; 11. 瀏覽器召集了在座的各位<span><ul><li>們,“大伙兒收拾收拾行李,咱得重新來(lái)過(guò)……”,瀏覽器向服務(wù)器請(qǐng)求了新的CSS文件,重新渲染頁(yè)面。 so...頁(yè)面為什么會(huì)慢?那是因?yàn)闉g覽器要花時(shí)間、花精力去渲染,尤其是當(dāng)它發(fā)現(xiàn)某個(gè)部分發(fā)生了點(diǎn)變化影響了布局,需要倒回去重新渲染,內(nèi)行稱這個(gè)回退的過(guò)程叫reflow。reflow問(wèn)題是可以優(yōu)化的,我們可以盡量減少不必要的reflow。比如開(kāi)頭的例子中的<img>圖片載入問(wèn)題,這其實(shí)就是一個(gè)可以避免的reflow——給圖片設(shè)置寬度和高度就可以了。這樣瀏覽器就知道了圖片的占位面積,在載入圖片前就預(yù)留好了位置。
另外,有個(gè)和reflow看上去差不多的術(shù)語(yǔ):repaint,中文叫重繪。 如果只是改變某個(gè)元素的背景色、文字顏色、邊框顏色等等不影響它周?chē)騼?nèi)部布局的屬性,將只會(huì)引起瀏覽器repaint。repaint的速度明顯快于 reflow(在IE下需要換一下說(shuō)法,reflow要比repaint 更緩慢)
?
三、從瀏覽器的渲染原理講CSS性能
?
平時(shí)我們幾乎每天都在和瀏覽器打交道,寫(xiě)出來(lái)的頁(yè)面很有可能在不同的瀏覽器下顯示的不一樣。苦逼的前端攻城師們?yōu)榱思嫒莞鱾€(gè)瀏覽器而不斷地去測(cè)試和調(diào)試,還在腦子中記下各種遇到的BUG及解決方案,而我們好像并沒(méi)有去主動(dòng)地關(guān)注和了解下瀏覽器的工作原理。如果我們對(duì)此做一點(diǎn)了解,我想在項(xiàng)目過(guò)程中就可以根據(jù)它有效的避免一些問(wèn)題以及對(duì)頁(yè)面性能做出相應(yīng)的改進(jìn)。
我們來(lái)看一下加載頁(yè)面時(shí)瀏覽器的具體工作流程:
1、解析HTML以重建DOM樹(shù)(Parsing HTML to construct the DOM tree ):渲染引擎開(kāi)始解析HTML文檔,轉(zhuǎn)換樹(shù)中的標(biāo)簽到DOM節(jié)點(diǎn),它被稱為“內(nèi)容樹(shù)”。
2、構(gòu)建渲染樹(shù)(Render tree construction):解析CSS(包括外部CSS文件和樣式元素),根據(jù)CSS選擇器計(jì)算出節(jié)點(diǎn)的樣式,創(chuàng)建另一個(gè)樹(shù) —- 渲染樹(shù)。
3、布局渲染樹(shù)(Layout of the render tree):?從根節(jié)點(diǎn)遞歸調(diào)用,計(jì)算每一個(gè)元素的大小、位置等,給每個(gè)節(jié)點(diǎn)所應(yīng)該出現(xiàn)在屏幕上的精確坐標(biāo)。
4、繪制渲染樹(shù)(Painting the render tree)?: 遍歷渲染樹(shù),每個(gè)節(jié)點(diǎn)將使用UI后端層來(lái)繪制。
主要的流程就是:構(gòu)建一個(gè)dom樹(shù),頁(yè)面要顯示的各元素都會(huì)創(chuàng)建到這個(gè)dom樹(shù)當(dāng)中,每當(dāng)一個(gè)新元素加入到這個(gè)dom樹(shù)當(dāng)中,瀏覽器便會(huì)通過(guò)css引擎查遍css樣式表,找到符合該元素的樣式規(guī)則應(yīng)用到這個(gè)元素上。
注意了:css引擎查找樣式表,對(duì)每條規(guī)則都按從右到左的順序去匹配。 看如下規(guī)則:
| 1 | #nav??li {} |
看起來(lái)很快,實(shí)際上很慢,盡管這讓人有點(diǎn)費(fèi)解#_#。我們中的大多數(shù)人,尤其是那些從左到右閱讀的人,可能猜想瀏覽器也是執(zhí)行從左到右匹配規(guī)則的,因此會(huì)推測(cè)這條規(guī)則的開(kāi)銷(xiāo)并不高。在腦海中,我們想象瀏覽器會(huì)像這樣工作:找到唯一的ID為nav的元素,然后把這個(gè)樣式應(yīng)用到直系子元素的li元素上。我們知道有一個(gè)ID為nav的元素,并且它只有幾個(gè)Li子元素,所以這個(gè)CSS選擇符應(yīng)該相當(dāng)高效。
事實(shí)上,CSS選擇符是從右到左進(jìn)行匹配的。了解這方面的知識(shí)后,我們知道這個(gè)之前看似高效地規(guī)則實(shí)際開(kāi)銷(xiāo)相當(dāng)高,瀏覽器必須遍歷頁(yè)面上每個(gè)li元素并確定其父元素的id是否為nav。
| 1 | *{} |
額,這種方法我剛寫(xiě)CSS的也寫(xiě)過(guò),殊不知這種效率是差到極點(diǎn)的做法,因?yàn)?通配符將匹配所有元素,所以瀏覽器必須去遍歷每一個(gè)元素,這樣的計(jì)算次數(shù)可能是上萬(wàn)次!
| 1 | ul#nav{} ul.nav{} |
在頁(yè)面中一個(gè)指定的ID只能對(duì)應(yīng)一個(gè)元素,所以沒(méi)有必要添加額外的限定符,而且這會(huì)使它更低效。同時(shí)也不要用具體的標(biāo)簽限定類(lèi)選擇符,而是要根據(jù)實(shí)際的情況對(duì)類(lèi)名進(jìn)行擴(kuò)展。例如把ul.nav改成.main_nav更好。
| 1 | ul li li li .nav_item{} |
對(duì)于這樣的選擇器,之前也寫(xiě)過(guò),最后自己也數(shù)不過(guò)來(lái)有多少后代選擇器了,何不用一個(gè)類(lèi)來(lái)關(guān)聯(lián)最后的標(biāo)簽元素,如.extra_navitem,這樣只需要匹配class為extra_navitem的元素,效率明顯提升了
對(duì)此,在CSS書(shū)寫(xiě)過(guò)程中,總結(jié)出如下性能提升的方案:
?? 選用高效的選擇符,可以減少頁(yè)面的渲染時(shí)間,從而有效的提升用戶體驗(yàn),你可以看一下CSS selectors Test,這個(gè)實(shí)驗(yàn)的重點(diǎn)是評(píng)估復(fù)雜選擇符和簡(jiǎn)單選擇符的開(kāi)銷(xiāo)。也許當(dāng)你想讓渲染速度最高效時(shí),你可能會(huì)給每個(gè)獨(dú)立的標(biāo)簽配置一個(gè)ID,然后用這些ID寫(xiě)樣式。那的確會(huì)超級(jí)快,也超級(jí)荒唐!這樣的結(jié)果是語(yǔ)義極差,后期的維護(hù)難到了極點(diǎn)。
?
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/luodatou/p/5463854.html
總結(jié)
- 上一篇: 兼容浏览器将NodeList对象转换为数
- 下一篇: 前端开发中的一些js小技巧