溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

瀏覽器的工作原理是什么

發(fā)布時(shí)間:2021-11-02 17:47:58 來源:億速云 閱讀:140 作者:iii 欄目:web開發(fā)

本篇內(nèi)容主要講解“瀏覽器的工作原理是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“瀏覽器的工作原理是什么”吧!

瀏覽器架構(gòu)

在講瀏覽器架構(gòu)之前,先理解兩個(gè)概念,進(jìn)程和線程。

進(jìn)程(process)是程序的一次執(zhí)行過程,是一個(gè)動態(tài)概念,是程序在執(zhí)行過程中分配和管理資源的基本單位,線程(thread)是CPU調(diào)度和分派的基本單位,它可與同屬一個(gè)進(jìn)程的其他的線程共享進(jìn)程所擁有的全部資源。

簡單的說呢,進(jìn)程可以理解成正在執(zhí)行的應(yīng)用程序,而線程呢,可以理解成我們應(yīng)用程序中的代碼的執(zhí)行器。而他們的關(guān)系可想而知,線程是跑在進(jìn)程里面的,一個(gè)進(jìn)程里面可能有一個(gè)或者多個(gè)線程,而一個(gè)線程,只能隸屬于一個(gè)進(jìn)程。

大家都知道,瀏覽器屬于一個(gè)應(yīng)用程序,而應(yīng)用程序的一次執(zhí)行,可以理解為計(jì)算機(jī)啟動了一個(gè)進(jìn)程,進(jìn)程啟動后,CPU會給該進(jìn)程分配相應(yīng)的內(nèi)存空間,當(dāng)我們的進(jìn)程得到了內(nèi)存之后,就可以使用線程進(jìn)行資源調(diào)度,進(jìn)而完成我們應(yīng)用程序的功能。

而在應(yīng)用程序中,為了滿足功能的需要,啟動的進(jìn)程會創(chuàng)建另外的新的進(jìn)程來處理其他任務(wù),這些創(chuàng)建出來的新的進(jìn)程擁有全新的獨(dú)立的內(nèi)存空間,不能與原來的進(jìn)程內(nèi)向內(nèi)存,如果這些進(jìn)程之間需要通信,可以通過IPC機(jī)制(Inter Process Communication)來進(jìn)行。

瀏覽器的工作原理是什么

很多應(yīng)用程序都會采取這種多進(jìn)程的方式來工作,因?yàn)檫M(jìn)程和進(jìn)程之間是互相獨(dú)立的它們互不影響,也就是說,當(dāng)其中一個(gè)進(jìn)程掛掉了之后,不會影響到其他進(jìn)程的執(zhí)行,只需要重啟掛掉的進(jìn)程就可以恢復(fù)運(yùn)行。

瀏覽器的多進(jìn)程架構(gòu)

假如我們?nèi)ラ_發(fā)一個(gè)瀏覽器,它的架構(gòu)可以是一個(gè)單進(jìn)程多線程的應(yīng)用程序,也可以是一個(gè)使用IPC通信的多進(jìn)程應(yīng)用程序。

不同的瀏覽器使用不同的架構(gòu),下面主要以Chrome為例,介紹瀏覽器的多進(jìn)程架構(gòu)。

在Chrome中,主要的進(jìn)程有4個(gè):

  •  瀏覽器進(jìn)程 (Browser Process):負(fù)責(zé)瀏覽器的TAB的前進(jìn)、后退、地址欄、書簽欄的工作和處理瀏覽器的一些不可見的底層操作,比如網(wǎng)絡(luò)請求和文件訪問。

  •  渲染進(jìn)程 (Renderer Process):負(fù)責(zé)一個(gè)Tab內(nèi)的顯示相關(guān)的工作,也稱渲染引擎。

  •  插件進(jìn)程 (Plugin Process):負(fù)責(zé)控制網(wǎng)頁使用到的插件

  •  GPU進(jìn)程 (GPU Process):負(fù)責(zé)處理整個(gè)應(yīng)用程序的GPU任務(wù)

瀏覽器的工作原理是什么

這4個(gè)進(jìn)程之間的關(guān)系是什么呢?

首先,當(dāng)我們是要瀏覽一個(gè)網(wǎng)頁,我們會在瀏覽器的地址欄里輸入U(xiǎn)RL,這個(gè)時(shí)候Browser Process會向這個(gè)URL發(fā)送請求,獲取這個(gè)URL的HTML內(nèi)容,然后將HTML交給Renderer Process,Renderer Process解析HTML內(nèi)容,解析遇到需要請求網(wǎng)絡(luò)的資源又返回來交給Browser Process進(jìn)行加載,同時(shí)通知Browser Process,需要Plugin Process加載插件資源,執(zhí)行插件代碼。解析完成后,Renderer Process計(jì)算得到圖像幀,并將這些圖像幀交給GPU Process,GPU Process將其轉(zhuǎn)化為圖像顯示屏幕。

瀏覽器的工作原理是什么

多進(jìn)程架構(gòu)的好處

Chrome為什么要使用多進(jìn)程架構(gòu)呢?

第一,更高的容錯(cuò)性。當(dāng)今WEB應(yīng)用中,HTML,JavaScript和CSS日益復(fù)雜,這些跑在渲染引擎的代碼,頻繁的出現(xiàn)BUG,而有些BUG會直接導(dǎo)致渲染引擎崩潰,多進(jìn)程架構(gòu)使得每一個(gè)渲染引擎運(yùn)行在各自的進(jìn)程中,相互之間不受影響,也就是說,當(dāng)其中一個(gè)頁面崩潰掛掉之后,其他頁面還可以正常的運(yùn)行不收影響。

瀏覽器的工作原理是什么

第二,更高的安全性和沙盒性(sanboxing)。渲染引擎會經(jīng)常性的在網(wǎng)絡(luò)上遇到不可信、甚至是惡意的代碼,它們會利用這些漏洞在你的電腦上安裝惡意的軟件,針對這一問題,瀏覽器對不同進(jìn)程限制了不同的權(quán)限,并為其提供沙盒運(yùn)行環(huán)境,使其更安全更可靠

第三,更高的響應(yīng)速度。在單進(jìn)程的架構(gòu)中,各個(gè)任務(wù)相互競爭搶奪CPU資源,使得瀏覽器響應(yīng)速度變慢,而多進(jìn)程架構(gòu)正好規(guī)避了這一缺點(diǎn)。

多進(jìn)程架構(gòu)優(yōu)化

之前的我們說到,Renderer Process的作用是負(fù)責(zé)一個(gè)Tab內(nèi)的顯示相關(guān)的工作,這就意味著,一個(gè)Tab,就會有一個(gè)Renderer Process,這些進(jìn)程之間的內(nèi)存無法進(jìn)行共享,而不同進(jìn)程的內(nèi)存常常需要包含相同的內(nèi)容。

瀏覽器的進(jìn)程模式

為了節(jié)省內(nèi)存,Chrome提供了四種進(jìn)程模式(Process Models),不同的進(jìn)程模式會對 tab 進(jìn)程做不同的處理。

  •  Process-per-site-instance (default) - 同一個(gè) site-instance 使用一個(gè)進(jìn)程

  •  Process-per-site - 同一個(gè) site 使用一個(gè)進(jìn)程

  •  Process-per-tab - 每個(gè) tab 使用一個(gè)進(jìn)程

  •  Single process - 所有 tab 共用一個(gè)進(jìn)程

這里需要給出 site 和 site-instance 的定義

  •  site 指的是相同的 registered domain name(如: google.com ,bbc.co.uk)和scheme (如:https://)。比如a.baidu.com和b.baidu.com就可以理解為同一個(gè) site(注意這里要和 Same-origin policy 區(qū)分開來,同源策略還涉及到子域名和端口)。

  •  site-instance 指的是一組 connected pages from the same site,這里 connected 的定義是 can obtain references to each other in script code 怎么理解這段話呢。滿足下面兩中情況并且打開的新頁面和舊頁面屬于上面定義的同一個(gè) site,就屬于同一個(gè) site-instance

    •   用戶通過<a target="_blank">這種方式點(diǎn)擊打開的新頁面

    •   JS代碼打開的新頁面(比如 window.open)

理解了概念之后,下面解釋四個(gè)進(jìn)程模式

首先是Single process,顧名思義,單進(jìn)程模式,所有tab都會使用同一個(gè)進(jìn)程。接下來是Process-per-tab ,也是顧名思義,每打開一個(gè)tab,會新建一個(gè)進(jìn)程。而對于Process-per-site,當(dāng)你打開 a.baidu.com 頁面,在打開 b.baidu.com 的頁面,這兩個(gè)頁面的tab使用的是共一個(gè)進(jìn)程,因?yàn)檫@兩個(gè)頁面的site相同,而如此一來,如果其中一個(gè)tab崩潰了,而另一個(gè)tab也會崩潰。

Process-per-site-instance 是最重要的,因?yàn)檫@個(gè)是 Chrome 默認(rèn)使用的模式,也就是幾乎所有的用戶都在用的模式。當(dāng)你打開一個(gè) tab 訪問 a.baidu.com ,然后再打開一個(gè) tab 訪問 b.baidu.com,這兩個(gè) tab 會使用兩個(gè)進(jìn)程。而如果你在 a.baidu.com 中,通過JS代碼打開了 b.baidu.com 頁面,這兩個(gè) tab 會使用同一個(gè)進(jìn)程。

默認(rèn)模式選擇

那么為什么瀏覽器使用Process-per-site-instance作為默認(rèn)的進(jìn)程模式呢?

Process-per-site-instance兼容了性能與易用性,是一個(gè)比較中庸通用的模式。

  •  相較于 Process-per-tab,能夠少開很多進(jìn)程,就意味著更少的內(nèi)存占用

  •  相較于 Process-per-site,能夠更好的隔離相同域名下毫無關(guān)聯(lián)的 tab,更加安全

導(dǎo)航過程都發(fā)生了什么

前面我們講了瀏覽器的多進(jìn)程架構(gòu),講了多進(jìn)程架構(gòu)的各種好處,和Chrome是怎么優(yōu)化多進(jìn)程架構(gòu)的,下面從用戶瀏覽網(wǎng)頁這一簡單的場景,來深入了解進(jìn)程和線程是如何呈現(xiàn)我們的網(wǎng)站頁面的。

網(wǎng)頁加載過程

之前我們我們提到,tab以外的大部分工作由瀏覽器進(jìn)程Browser Process負(fù)責(zé),針對工作的不同,Browser Process 劃分出不同的工作線程:

  •  UI thread:控制瀏覽器上的按鈕及輸入框;

  •  network thread:處理網(wǎng)絡(luò)請求,從網(wǎng)上獲取數(shù)據(jù);

  •  storage thread: 控制文件等的訪問;

瀏覽器的工作原理是什么

第一步:處理輸入

當(dāng)我們在瀏覽器的地址欄輸入內(nèi)容按下回車時(shí),UI thread會判斷輸入的內(nèi)容是搜索關(guān)鍵詞(search query)還是URL,如果是搜索關(guān)鍵詞,跳轉(zhuǎn)至默認(rèn)搜索引擎對應(yīng)都搜索URL,如果輸入的內(nèi)容是URL,則開始請求URL。

瀏覽器的工作原理是什么

第二步:開始導(dǎo)航

回車按下后,UI thread將關(guān)鍵詞搜索對應(yīng)的URL或輸入的URL交給網(wǎng)絡(luò)線程N(yùn)etwork thread,此時(shí)UI線程使Tab前的圖標(biāo)展示為加載中狀態(tài),然后網(wǎng)絡(luò)進(jìn)程進(jìn)行一系列諸如DNS尋址,建立TLS連接等操作進(jìn)行資源請求,如果收到服務(wù)器的301重定向響應(yīng),它就會告知UI線程進(jìn)行重定向然后它會再次發(fā)起一個(gè)新的網(wǎng)絡(luò)請求。

瀏覽器的工作原理是什么

第三步:讀取響應(yīng)

network thread接收到服務(wù)器的響應(yīng)后,開始解析HTTP響應(yīng)報(bào)文,然后根據(jù)響應(yīng)頭中的Content-Type字段來確定響應(yīng)主體的媒體類型(MIME Type),如果媒體類型是一個(gè)HTML文件,則將響應(yīng)數(shù)據(jù)交給渲染進(jìn)程(renderer process)來進(jìn)行下一步的工作,如果是 zip 文件或者其它文件,會把相關(guān)數(shù)據(jù)傳輸給下載管理器。

與此同時(shí),瀏覽器會進(jìn)行 Safe Browsing 安全檢查,如果域名或者請求內(nèi)容匹配到已知的惡意站點(diǎn),network thread 會展示一個(gè)警告頁。除此之外,網(wǎng)絡(luò)線程還會做 CORB(Cross Origin Read Blocking)檢查來確定那些敏感的跨站數(shù)據(jù)不會被發(fā)送至渲染進(jìn)程。

第四步:查找渲染進(jìn)程

各種檢查完畢以后,network thread 確信瀏覽器可以導(dǎo)航到請求網(wǎng)頁,network thread 會通知 UI thread 數(shù)據(jù)已經(jīng)準(zhǔn)備好,UI thread 會查找到一個(gè) renderer process 進(jìn)行網(wǎng)頁的渲染。

瀏覽器的工作原理是什么

瀏覽器為了對查找渲染進(jìn)程這一步驟進(jìn)行優(yōu)化,考慮到網(wǎng)絡(luò)請求獲取響應(yīng)需要時(shí)間,所以在第二步開始,瀏覽器已經(jīng)預(yù)先查找和啟動了一個(gè)渲染進(jìn)程,如果中間步驟一切順利,當(dāng) network thread 接收到數(shù)據(jù)時(shí),渲染進(jìn)程已經(jīng)準(zhǔn)備好了,但是如果遇到重定向,這個(gè)準(zhǔn)備好的渲染進(jìn)程也許就不可用了,這個(gè)時(shí)候會重新啟動一個(gè)渲染進(jìn)程。

第五步:提交導(dǎo)航

到了這一步,數(shù)據(jù)和渲染進(jìn)程都準(zhǔn)備好了,Browser Process 會向 Renderer Process 發(fā)送IPC消息來確認(rèn)導(dǎo)航,此時(shí),瀏覽器進(jìn)程將準(zhǔn)備好的數(shù)據(jù)發(fā)送給渲染進(jìn)程,渲染進(jìn)程接收到數(shù)據(jù)之后,又發(fā)送IPC消息給瀏覽器進(jìn)程,告訴瀏覽器進(jìn)程導(dǎo)航已經(jīng)提交了,頁面開始加載。

瀏覽器的工作原理是什么

這個(gè)時(shí)候?qū)Ш綑跁拢踩甘痉拢ǖ刂非懊娴男℃i),訪問歷史列表(history tab)更新,即可以通過前進(jìn)后退來切換該頁面。

第六步:初始化加載完成

當(dāng)導(dǎo)航提交完成后,渲染進(jìn)程開始加載資源及渲染頁面(詳細(xì)內(nèi)容下文介紹),當(dāng)頁面渲染完成后(頁面及內(nèi)部的iframe都觸發(fā)了onload事件),會向?yàn)g覽器進(jìn)程發(fā)送IPC消息,告知瀏覽器進(jìn)程,這個(gè)時(shí)候UI thread會停止展示tab中的加載中圖標(biāo)。

網(wǎng)頁渲染原理

導(dǎo)航過程完成之后,瀏覽器進(jìn)程把數(shù)據(jù)交給了渲染進(jìn)程,渲染進(jìn)程負(fù)責(zé)tab內(nèi)的所有事情,核心目的就是將HTML/CSS/JS代碼,轉(zhuǎn)化為用戶可進(jìn)行交互的web頁面。那么渲染進(jìn)程是如何工作的呢?

渲染進(jìn)程中,包含線程分別是:

  •  一個(gè)主線程(main thread)

  •  多個(gè)工作線程(work thread)

  •  一個(gè)合成器線程(compositor thread)

  •  多個(gè)光柵化線程(raster thread)

瀏覽器的工作原理是什么

不同的線程,有著不同的工作職責(zé)。

構(gòu)建DOM

當(dāng)渲染進(jìn)程接受到導(dǎo)航的確認(rèn)信息后,開始接受來自瀏覽器進(jìn)程的數(shù)據(jù),這個(gè)時(shí)候,主線程會解析數(shù)據(jù)轉(zhuǎn)化為DOM(Document Object Model)對象。

DOM為WEB開發(fā)人員通過JavaScript與網(wǎng)頁進(jìn)行交互的數(shù)據(jù)結(jié)構(gòu)及API。

資源子加載

在構(gòu)建DOM的過程中,會解析到圖片、CSS、JavaScript腳本等資源,這些資源是需要從網(wǎng)絡(luò)或者緩存中獲取的,主線程在構(gòu)建DOM過程中如果遇到了這些資源,逐一發(fā)起請求去獲取,而為了提升效率,瀏覽器也會運(yùn)行預(yù)加載掃描(preload scanner)程序,如果如果HTML中存在img、link等標(biāo)簽,預(yù)加載掃描程序會把這些請求傳遞給Browser Process的network thread進(jìn)行資源下載。

瀏覽器的工作原理是什么

JavaScript的下載與執(zhí)行

構(gòu)建DOM過程中,如果遇到<script>標(biāo)簽,渲染引擎會停止對HTML的解析,而去加載執(zhí)行JS代碼,原因在于JS代碼可能會改變DOM的結(jié)構(gòu)(比如執(zhí)行document.write()等API)

不過開發(fā)者其實(shí)也有多種方式來告知瀏覽器應(yīng)對如何應(yīng)對某個(gè)資源,比如說如果在<script> 標(biāo)簽上添加了 async 或 defer 等屬性,瀏覽器會異步的加載和執(zhí)行JS代碼,而不會阻塞渲染。

樣式計(jì)算 - Style calculation

DOM樹只是我們頁面的結(jié)構(gòu),我們要知道頁面長什么樣子,我們還需要知道DOM的每一個(gè)節(jié)點(diǎn)的樣式。主線程在解析頁面時(shí),遇到<style>標(biāo)簽或者<link>標(biāo)簽的CSS資源,會加載CSS代碼,根據(jù)CSS代碼確定每個(gè)DOM節(jié)點(diǎn)的計(jì)算樣式(computed style)。

計(jì)算樣式是主線程根據(jù)CSS樣式選擇器(CSS selectors)計(jì)算出的每個(gè)DOM元素應(yīng)該具備的具體樣式,即使你的頁面沒有設(shè)置任何自定義的樣式,瀏覽器也會提供其默認(rèn)的樣式。

瀏覽器的工作原理是什么

布局 - Layout

DOM樹和計(jì)算樣式完成后,我們還需要知道每一個(gè)節(jié)點(diǎn)在頁面上的位置,布局(Layout)其實(shí)就是找到所有元素的幾何關(guān)系的過程。

主線程會遍歷DOM 及相關(guān)元素的計(jì)算樣式,構(gòu)建出包含每個(gè)元素的頁面坐標(biāo)信息及盒子模型大小的布局樹(Render Tree),遍歷過程中,會跳過隱藏的元素(display: none),另外,偽元素雖然在DOM上不可見,但是在布局樹上是可見的。

瀏覽器的工作原理是什么

繪制 - Paint

布局 layout 之后,我們知道了不同元素的結(jié)構(gòu),樣式,幾何關(guān)系,我們要繪制出一個(gè)頁面,我們要需要知道每個(gè)元素的繪制先后順序,在繪制階段,主線程會遍歷布局樹(layout tree),生成一系列的繪畫記錄(paint records)。繪畫記錄可以看做是記錄各元素繪制先后順序的筆記。

瀏覽器的工作原理是什么

合成 - Compositing

文檔結(jié)構(gòu)、元素的樣式、元素的幾何關(guān)系、繪畫順序,這些信息我們都有了,這個(gè)時(shí)候如果要繪制一個(gè)頁面,我們需要做的是把這些信息轉(zhuǎn)化為顯示器中的像素,這個(gè)轉(zhuǎn)化的過程,叫做光柵化(rasterizing)。

那我們要繪制一個(gè)頁面,最簡單的做法是只光柵化視口內(nèi)(viewport)的網(wǎng)頁內(nèi)容,如果用戶進(jìn)行了頁面滾動,就移動光柵幀(rastered frame)并且光柵化更多的內(nèi)容以補(bǔ)上頁面缺失的部分,如下:

瀏覽器的工作原理是什么

最簡單的光柵化過程

Chrome第一個(gè)版本就是采用這種簡單的繪制方式,這一方式唯一的缺點(diǎn)就是每當(dāng)頁面滾動,光柵線程都需要對新移進(jìn)視圖的內(nèi)容進(jìn)行光柵化,這是一定的性能損耗,為了優(yōu)化這種情況,Chrome采取一種更加復(fù)雜的叫做合成(compositing)的做法。

那么,什么是合成?合成是一種將頁面分成若干層,然后分別對它們進(jìn)行光柵化,最后在一個(gè)單獨(dú)的線程 - 合成線程(compositor thread)里面合并成一個(gè)頁面的技術(shù)。當(dāng)用戶滾動頁面時(shí),由于頁面各個(gè)層都已經(jīng)被光柵化了,瀏覽器需要做的只是合成一個(gè)新的幀來展示滾動后的效果罷了。頁面的動畫效果實(shí)現(xiàn)也是類似,將頁面上的層進(jìn)行移動并構(gòu)建出一個(gè)新的幀即可。

瀏覽器的工作原理是什么

為了實(shí)現(xiàn)合成技術(shù),我們需要對元素進(jìn)行分層,確定哪些元素需要放置在哪一層,主線程需要遍歷渲染樹來創(chuàng)建一棵層次樹(Layer Tree),對于添加了 will-change CSS 屬性的元素,會被看做單獨(dú)的一層,沒有 will-change CSS屬性的元素,瀏覽器會根據(jù)情況決定是否要把該元素放在單獨(dú)的層。

瀏覽器的工作原理是什么

你可能會想要給頁面上所有的元素一個(gè)單獨(dú)的層,然而當(dāng)頁面的層超過一定的數(shù)量后,層的合成操作要比在每個(gè)幀中光柵化頁面的一小部分還要慢,因此衡量你應(yīng)用的渲染性能是十分重要的一件事情。

一旦Layer Tress被創(chuàng)建,渲染順序被確定,主線程會把這些信息通知給合成器線程,合成器線程開始對層次數(shù)的每一層進(jìn)行光柵化。有的層的可以達(dá)到整個(gè)頁面的大小,所以合成線程需要將它們切分為一塊又一塊的小圖塊(tiles),之后將這些小圖塊分別進(jìn)行發(fā)送給一系列光柵線程(raster threads)進(jìn)行光柵化,結(jié)束后光柵線程會將每個(gè)圖塊的光柵結(jié)果存在GPU Process的內(nèi)存中。

瀏覽器的工作原理是什么

為了優(yōu)化顯示體驗(yàn),合成線程可以給不同的光柵線程賦予不同的優(yōu)先級,將那些在視口中的或者視口附近的層先被光柵化。

當(dāng)圖層上面的圖塊都被柵格化后,合成線程會收集圖塊上面叫做繪畫四邊形(draw quads)的信息來構(gòu)建一個(gè)合成幀(compositor frame)。

  •  繪畫四邊形:包含圖塊在內(nèi)存的位置以及圖層合成后圖塊在頁面的位置之類的信息。

  •  合成幀:代表頁面一個(gè)幀的內(nèi)容的繪制四邊形集合。

以上所有步驟完成后,合成線程就會通過IPC向?yàn)g覽器進(jìn)程(browser process)提交(commit)一個(gè)渲染幀。這個(gè)時(shí)候可能有另外一個(gè)合成幀被瀏覽器進(jìn)程的UI線程(UI thread)提交以改變?yōu)g覽器的UI。這些合成幀都會被發(fā)送給GPU從而展示在屏幕上。如果合成線程收到頁面滾動的事件,合成線程會構(gòu)建另外一個(gè)合成幀發(fā)送給GPU來更新頁面。

瀏覽器的工作原理是什么

合成的好處在于這個(gè)過程沒有涉及到主線程,所以合成線程不需要等待樣式的計(jì)算以及JavaScript完成執(zhí)行。這就是為什么rocks.com/en/tutorials/speed/high-performance-animations/" _fcksavedurl="https://www.html5rocks.com/en/tutorials/speed/high-performance-animations/">合成器相關(guān)的動畫最流暢,如果某個(gè)動畫涉及到布局或者繪制的調(diào)整,就會涉及到主線程的重新計(jì)算,自然會慢很多。

瀏覽器對事件的處理

當(dāng)頁面渲染完畢以后,TAB內(nèi)已經(jīng)顯示出了可交互的WEB頁面,用戶可以進(jìn)行移動鼠標(biāo)、點(diǎn)擊頁面等操作了,而當(dāng)這些事件發(fā)生時(shí)候,瀏覽器是如何處理這些事件的呢?

以點(diǎn)擊事件(click event)為例,讓鼠標(biāo)點(diǎn)擊頁面時(shí)候,首先接受到事件信息的是Browser Process,但是Browser Process只知道事件發(fā)生的類型和發(fā)生的位置,具體怎么對這個(gè)點(diǎn)擊事件進(jìn)行處理,還是由Tab內(nèi)的Renderer Process進(jìn)行的。Browser Process接受到事件后,隨后便把事件的信息傳遞給了渲染進(jìn)程,渲染進(jìn)程會找到根據(jù)事件發(fā)生的坐標(biāo),找到目標(biāo)對象(target),并且運(yùn)行這個(gè)目標(biāo)對象的點(diǎn)擊事件綁定的監(jiān)聽函數(shù)(listener)。

瀏覽器的工作原理是什么

渲染進(jìn)程中合成器線程接收事件

前面我們說到,合成器線程可以獨(dú)立于主線程之外通過已光柵化的層創(chuàng)建組合幀,例如頁面滾動,如果沒有對頁面滾動綁定相關(guān)的事件,組合器線程可以獨(dú)立于主線程創(chuàng)建組合幀,如果頁面綁定了頁面滾動事件,合成器線程會等待主線程進(jìn)行事件處理后才會創(chuàng)建組合幀。那么,合成器線程是如何判斷出這個(gè)事件是否需要路由給主線程處理的呢?

由于執(zhí)行 JS 是主線程的工作,當(dāng)頁面合成時(shí),合成器線程會標(biāo)記頁面中綁定有事件處理器的區(qū)域?yàn)榉强焖贊L動區(qū)域(non-fast scrollable region),如果事件發(fā)生在這些存在標(biāo)注的區(qū)域,合成器線程會把事件信息發(fā)送給主線程,等待主線程進(jìn)行事件處理,如果事件不是發(fā)生在這些區(qū)域,合成器線程則會直接合成新的幀而不用等到主線程的響應(yīng)。

瀏覽器的工作原理是什么

而對于非快速滾動區(qū)域的標(biāo)記,開發(fā)者需要注意全局事件的綁定,比如我們使用事件委托,將目標(biāo)元素的事件交給根元素body進(jìn)行處理,代碼如下:

document.body.addEventListener('touchstart', event => {    if (event.target === area) {      event.preventDefault()    }  })

在開發(fā)者角度看,這一段代碼沒什么問題,但是從瀏覽器角度看,這一段代碼給body元素綁定了事件監(jiān)聽器,也就意味著整個(gè)頁面都被編輯為一個(gè)非快速滾動區(qū)域,這會使得即使你的頁面的某些區(qū)域沒有綁定任何事件,每次用戶觸發(fā)事件時(shí),合成器線程也需要和主線程通信并等待反饋,流暢的合成器獨(dú)立處理合成幀的模式就失效了。

瀏覽器的工作原理是什么

其實(shí)這種情況也很好處理,只需要在事件監(jiān)聽時(shí)傳遞passtive參數(shù)為 true,passtive會告訴瀏覽器你既要綁定事件,又要讓組合器線程直接跳過主線程的事件處理直接合成創(chuàng)建組合幀。

document.body.addEventListener('touchstart', ?event => {      if (event.target === area) {          event.preventDefault()      }   }, {passive: true});

查找事件的目標(biāo)對象(event target)

當(dāng)合成器線程接收到事件信息,判定到事件發(fā)生不在非快速滾動區(qū)域后,合成器線程會向主線程發(fā)送這個(gè)時(shí)間信息,主線程獲取到事件信息的第一件事就是通過命中測試(hit test)去找到事件的目標(biāo)對象。具體的命中測試流程是遍歷在繪制階段生成的繪畫記錄(paint records)來找到包含了事件發(fā)生坐標(biāo)上的元素對象。

瀏覽器的工作原理是什么

瀏覽器對事件的優(yōu)化

一般我們屏幕的幀率是每秒60幀,也就是60fps,但是某些事件觸發(fā)的頻率超過了這個(gè)數(shù)值,比如wheel,mousewheel,mousemove,pointermove,touchmove,這些連續(xù)性的事件一般每秒會觸發(fā)60~120次,假如每一次觸發(fā)事件都將事件發(fā)送到主線程處理,由于屏幕的刷新速率相對來說較低,這樣使得主線程會觸發(fā)過量的命中測試以及JS代碼,使得性能有了沒必要是損耗。

瀏覽器的工作原理是什么

出于優(yōu)化的目的,瀏覽器會合并這些連續(xù)的事件,延遲到下一幀渲染是執(zhí)行,也就是requestAnimationFrame之前。

瀏覽器的工作原理是什么

和之前相同的事件軸,可是這次事件被合并并延遲調(diào)度了

而對于非連續(xù)性的事件,如keydown,keyup,mousedown,mouseup,touchstart,touchend等,會直接派發(fā)給主線程去執(zhí)行。

到此,相信大家對“瀏覽器的工作原理是什么”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI