摘要:渲染引擎也稱為呈現(xiàn)引擎瀏覽器內(nèi)核,負(fù)責(zé)顯示請(qǐng)求的內(nèi)容。引擎是基于事件驅(qū)動(dòng)單線程執(zhí)行的,引擎一直等待著任務(wù)隊(duì)列中任務(wù)的到來(lái),然后加以處理,瀏覽器無(wú)論什么時(shí)候都只有一個(gè)線程在運(yùn)行程序。
1 瀏覽器結(jié)構(gòu)
瀏覽器分為以下7個(gè)部分:
用戶界面
瀏覽器引擎:在用戶界面和呈現(xiàn)引擎之間傳送指令。
渲染引擎:也稱為呈現(xiàn)引擎/瀏覽器內(nèi)核,負(fù)責(zé)顯示請(qǐng)求的內(nèi)容。
不同的瀏覽器有不同的呈現(xiàn)引擎,例如:
Chrome: Blink。Blink是Webkit的一個(gè)分支,添加了一些優(yōu)化新特性。
Safari: Webkit
Firfox: Gecko
IE: Trident
網(wǎng)絡(luò):用于網(wǎng)絡(luò)調(diào)用,比如 HTTP 請(qǐng)求。
用戶界面后端:用于繪制基本的窗口小部件,比如組合框和窗口。
JavaScript 解釋器:用于解析和執(zhí)行 JavaScript 代碼。又稱為 JavaScript 引擎,也可以成為 JavaScript 內(nèi)核,在線程方面又稱為 JavaScript 引擎線程。
同樣不同的瀏覽器有不同的JS解釋器,例如:
Chrome: V8引擎。之前是機(jī)器碼,最近重回字典碼
Safari: JavaScriptCore引擎
Firfox: Ion引擎
PS:不同瀏覽器間引擎性能差距不大,詳見(jiàn)https://arewefastyet.com
數(shù)據(jù)存儲(chǔ):這是持久層。瀏覽器需要在硬盤(pán)上保存各種數(shù)據(jù),例如 Cookie。
2 瀏覽器占比 2.1 PC瀏覽器占比2018年2月份占比
瀏覽器渲染引擎最重要的工作就是將 HTML 和 CSS 文檔解析組合最終渲染到瀏覽器窗口上。如下圖所示:
解析 HTML 構(gòu)建 DOM 樹(shù)時(shí)渲染引擎會(huì)將 HTML 文件的便簽元素解析成多個(gè) DOM 元素對(duì)象節(jié)點(diǎn),并且將這些節(jié)點(diǎn)根據(jù)父子關(guān)系組成一個(gè)樹(shù)結(jié)構(gòu)。同時(shí) CSS 文件被解析成 CSS 規(guī)則表,然后將每條 CSS 規(guī)則按照「從右向左」的方式在 DOM 樹(shù)上進(jìn)行逆向匹配,生成一個(gè)具有樣式規(guī)則描述的 DOM 渲染樹(shù)。接下來(lái)就是將渲染樹(shù)進(jìn)行布局、繪制的過(guò)程。首先根據(jù) DOM 渲染樹(shù)上的樣式規(guī)則,對(duì) DOM 元素進(jìn)行大小和位置的定位,關(guān)鍵屬性如position;width;margin;padding;top;border;...,接下來(lái)再根據(jù)元素樣式規(guī)則中的color;background;shadow;...規(guī)則進(jìn)行繪制。4 瀏覽器的進(jìn)程與線程 4.1 瀏覽器的進(jìn)程另外,這個(gè)過(guò)程是逐步完成的,為了更好的用戶體驗(yàn),渲染引擎將會(huì)盡可能早的將內(nèi)容呈現(xiàn)到屏幕上,并不會(huì)等到所有的 html 都解析完成之后再去構(gòu)建和布局 render 樹(shù)。它是解析完一部分內(nèi)容就顯示一部分內(nèi)容,同時(shí),可能還在通過(guò)網(wǎng)絡(luò)下載其余內(nèi)容。
再者,需要注意的是,在瀏覽器渲染完首屏頁(yè)面后,如果對(duì) DOM 進(jìn)行操作會(huì)引起瀏覽器引擎對(duì) DOM 渲染樹(shù)的重新布局和重新繪制,我們叫做「重排」和「重繪」,由于重排和重繪是前后依賴的關(guān)系,重繪發(fā)生時(shí)未必會(huì)觸發(fā)渲染引擎的重排,但是如果發(fā)生了重排就必然會(huì)觸發(fā)重繪操作,這樣帶來(lái)的性能損害就是巨大的。因此我們?cè)谧鲂阅軆?yōu)化的時(shí)候應(yīng)該遵循「避免重排;減少重繪」的原則。[1]
在瀏覽器剛被設(shè)計(jì)出來(lái)的時(shí)候,那時(shí)的網(wǎng)頁(yè)非常的簡(jiǎn)單,每個(gè)網(wǎng)頁(yè)的資源占有率是非常低的,因此一個(gè)進(jìn)程處理多個(gè)網(wǎng)頁(yè)時(shí)可行的。然后在今天,大量網(wǎng)頁(yè)變得日益復(fù)雜。把所有網(wǎng)頁(yè)都放進(jìn)一個(gè)進(jìn)程的瀏覽器面臨在健壯性,響應(yīng)速度,安全性方面的挑戰(zhàn)。因?yàn)槿绻麨g覽器中的一個(gè)tab網(wǎng)頁(yè)崩潰的話,將會(huì)導(dǎo)致其他被打開(kāi)的網(wǎng)頁(yè)應(yīng)用。另外相對(duì)于線程,進(jìn)程之間是不共享資源和地址空間的,所以不會(huì)存在太多的安全問(wèn)題,而由于多個(gè)線程共享著相同的地址空間和資源,所以會(huì)存在線程之間有可能會(huì)惡意修改或者獲取非授權(quán)數(shù)據(jù)等復(fù)雜的安全問(wèn)題。
因此Chrome瀏覽器針對(duì)每一個(gè)tab頁(yè)簽,都開(kāi)了一個(gè)進(jìn)程。
瀏覽器的內(nèi)核是多線程的,它們?cè)趦?nèi)核控制下相互配合以保持同步,一個(gè)瀏覽器大概會(huì)有以下幾個(gè)線程:JavaScript引擎線程,GUI渲染線程(又稱為UI主線程),瀏覽器事件觸發(fā)線程,異步 HTTP 請(qǐng)求線程(Chrome最多并發(fā)6個(gè))。
JavaScript引擎是基于事件驅(qū)動(dòng)單線程執(zhí)行的,JavaScript引擎一直等待著任務(wù)隊(duì)列中任務(wù)的到來(lái),然后加以處理,瀏覽器無(wú)論什么時(shí)候都只有一個(gè)JavaScript線程在運(yùn)行JavaScript程序。
var isEnd = true; window.setTimeout(function () { isEnd = false;//1s后,改變isEnd的值 }, 1000); //這個(gè)while永遠(yuǎn)的占用了js線程,所以setTimeout里面的函數(shù)永遠(yuǎn)不會(huì)執(zhí)行 while (isEnd);
GUI渲染線程負(fù)責(zé)渲染瀏覽器界面,當(dāng)界面需要重繪(Repaint)或由于某種操作引發(fā)回流(Reflow)時(shí),該線程就會(huì)執(zhí)行。但需要注意,GUI渲染線程與JavaScript引擎是互斥的,當(dāng)JavaScript引擎執(zhí)行時(shí)GUI線程會(huì)被掛起,GUI更新會(huì)被保存在一個(gè)隊(duì)列中等到JavaScript引擎空閑時(shí)立即被執(zhí)行。
事件觸發(fā)線程,當(dāng)一個(gè)事件被觸發(fā)時(shí),該線程會(huì)把事件添加到待處理隊(duì)列的隊(duì)尾,等待JavaScript引擎的處理。這些事件可來(lái)自JavaScript引擎當(dāng)前執(zhí)行的代碼塊如setTimeout、也可來(lái)自瀏覽器內(nèi)核的其他線程如鼠標(biāo)點(diǎn)擊、Ajax異步請(qǐng)求等,但由于JavaScript的單線程關(guān)系,所有這些事件都得排隊(duì)等待JavaScript引擎處理(當(dāng)線程中沒(méi)有執(zhí)行任何同步代碼的前提下才會(huì)執(zhí)行異步代碼)。[2]
console.log(1) setTimeout(function() { console.log(2) }, 0) console.log(3) // 輸出結(jié)果1,3,24.3 開(kāi)啟額外的線程-Web Worker
如下圖,耗時(shí)JS的同步加載會(huì)阻攔頁(yè)面的渲染,這時(shí)候如果有一個(gè)線程可以處理這個(gè)耗時(shí)js就好了。Web Worker可以創(chuàng)建一個(gè)新的進(jìn)程,來(lái)和UI主線程并發(fā)運(yùn)行。但是這個(gè)新進(jìn)程不能操作Dom對(duì)象, 只能用來(lái)處理復(fù)雜的JS的操作。
123
使用方法:
// main.js var worker = new Worker("task.js"); worker.postMessage( { id:1, msg:"Hello World" } ); worker.onmessage=function(message){ var data = message.data; console.log(JSON.stringify(data)); worker.terminate(); }; worker.onerror=function(error){ console.log(error.filename,error.lineno,error.message); } // task.js onmessage = function(message){ var data=message.data; data.msg = "Hi from task.js"; postMessage(data); }
可以看到,兩個(gè)js之間通過(guò)事件通訊。盡管Web Worker在大量數(shù)據(jù)的檢索、數(shù)據(jù)運(yùn)算上能提供一些幫助,但是使用面還是比較窄的。
5 頁(yè)面加載優(yōu)化《雅虎前端優(yōu)化35條規(guī)則翻譯》
《優(yōu)化JavaScript執(zhí)行》
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/93245.html
摘要:是用來(lái)在文檔中模擬協(xié)議的響應(yīng)頭報(bào)文。標(biāo)簽是語(yǔ)言區(qū)的一個(gè)輔助性標(biāo)簽,它位于文檔頭部的標(biāo)記和標(biāo)記之間,它提供用戶不可見(jiàn)的信息。 meta是用來(lái)在HTML文檔中模擬HTTP協(xié)議的響應(yīng)頭報(bào)文。META標(biāo)簽是HTML語(yǔ)言HEAD區(qū)的一個(gè)輔助性標(biāo)簽,它位于HTML文檔頭部的標(biāo)記和標(biāo)記之間,它提供用戶不可見(jiàn)的信息。meta標(biāo)簽通常用來(lái)為搜索引擎robots定義頁(yè)面主題,或者是定義用戶瀏覽器上的coo...
摘要:響應(yīng)式布局詳解之標(biāo)簽添加的屬性詳解表示設(shè)置屏幕按的尺寸顯示,在和其他智能手機(jī)的瀏覽器提供網(wǎng)站全視圖瀏覽,并禁止用戶縮放頁(yè)面。這個(gè)是的專用標(biāo)記,是用來(lái)指定瀏覽器模擬某個(gè)特定版本瀏覽器的渲染方式,以此來(lái)解決瀏覽器的兼容問(wèn)題。 響應(yīng)式布局詳解之head標(biāo)簽添加的屬性詳解 表示:設(shè)置屏幕按1:1的尺寸顯示,在 iPhone 和其他智能手機(jī)的瀏覽器提供網(wǎng)站全視圖瀏覽,并禁止用戶縮放頁(yè)面。 表...
摘要:響應(yīng)式布局詳解之標(biāo)簽添加的屬性詳解表示設(shè)置屏幕按的尺寸顯示,在和其他智能手機(jī)的瀏覽器提供網(wǎng)站全視圖瀏覽,并禁止用戶縮放頁(yè)面。這個(gè)是的專用標(biāo)記,是用來(lái)指定瀏覽器模擬某個(gè)特定版本瀏覽器的渲染方式,以此來(lái)解決瀏覽器的兼容問(wèn)題。 響應(yīng)式布局詳解之head標(biāo)簽添加的屬性詳解 表示:設(shè)置屏幕按1:1的尺寸顯示,在 iPhone 和其他智能手機(jī)的瀏覽器提供網(wǎng)站全視圖瀏覽,并禁止用戶縮放頁(yè)面。 表...
摘要:之前我們講了一下四種跨域的方式四種跨域方式詳解。這四種方式是使用純來(lái)進(jìn)行跨域的。今天就介紹兩種有涉及到服務(wù)器的跨域技術(shù)。 之前我們講了一下四種 JavaScript 跨域的方式 - 「JavaScript」四種跨域方式詳解。這四種方式是使用純 JavaScript 來(lái)進(jìn)行跨域的。 今天就介紹兩種有涉及到服務(wù)器的跨域技術(shù)。 一、反向代理服務(wù)器 基礎(chǔ)思想很簡(jiǎn)單,將你的服務(wù)器配置成 需要跨域...
閱讀 950·2021-11-24 09:38
閱讀 990·2021-11-23 09:51
閱讀 2982·2021-11-16 11:44
閱讀 1806·2021-09-22 15:52
閱讀 1712·2021-09-10 11:20
閱讀 1431·2019-08-30 13:47
閱讀 1334·2019-08-29 12:36
閱讀 3358·2019-08-26 10:43