<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          【瀏覽器】769- 你不知道的瀏覽器渲染原理

          共 10057字,需瀏覽 21分鐘

           ·

          2020-11-08 07:54


          原文地址:

          https://segmentfault.com/a/1190000022633988?_ea=44436475#item-4-8

          作者:_楊溜溜


          在我們面試過程中,面試官經(jīng)常會(huì)問到這么一個(gè)問題,那就是從在瀏覽器地址欄中輸入U(xiǎn)RL到頁面顯示,瀏覽器到底發(fā)生了什么?這個(gè)問題看起來是老生常談,但是這個(gè)問題回答的好壞,確實(shí)可以很好的反映出面試者知識(shí)的廣度和深度。

          本文從瀏覽器角度來告訴你,URL后輸入后按回車,瀏覽器內(nèi)部究竟發(fā)生了什么,讀完本文后,你將了解到:

          • 瀏覽器內(nèi)有哪些進(jìn)程,這些進(jìn)程都有些什么作用

          • 瀏覽器地址輸入U(xiǎn)RL后,內(nèi)部的進(jìn)程、線程都做了哪些事

          • 我們與瀏覽器交互時(shí),內(nèi)部進(jìn)程是怎么處理這些交互事件的

          瀏覽器架構(gòu)

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

          進(jìn)程(process)是程序的一次執(zhí)行過程,是一個(gè)動(dòng)態(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ī)啟動(dòng)了一個(gè)進(jìn)程,進(jìn)程啟動(dòng)后,CPU會(huì)給該進(jìn)程分配相應(yīng)的內(nèi)存空間,當(dāng)我們的進(jìn)程得到了內(nèi)存之后,就可以使用線程進(jìn)行資源調(diào)度,進(jìn)而完成我們應(yīng)用程序的功能。

          而在應(yīng)用程序中,為了滿足功能的需要,啟動(dòng)的進(jìn)程會(huì)創(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)用程序都會(huì)采取這種多進(jìn)程的方式來工作,因?yàn)檫M(jìn)程和進(jìn)程之間是互相獨(dú)立的它們互不影響,也就是說,當(dāng)其中一個(gè)進(jìn)程掛掉了之后,不會(huì)影響到其他進(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ò)請(qǐng)求和文件訪問。

          • 渲染進(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)頁,我們會(huì)在瀏覽器的地址欄里輸入U(xiǎn)RL,這個(gè)時(shí)候Browser Process會(huì)向這個(gè)URL發(fā)送請(qǐng)求,獲取這個(gè)URL的HTML內(nèi)容,然后將HTML交給Renderer ProcessRenderer Process解析HTML內(nèi)容,解析遇到需要請(qǐng)求網(wǎng)絡(luò)的資源又返回來交給Browser Process進(jìn)行加載,同時(shí)通知Browser Process,需要Plugin Process加載插件資源,執(zhí)行插件代碼。解析完成后,Renderer Process計(jì)算得到圖像幀,并將這些圖像幀交給GPU ProcessGPU 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會(huì)直接導(dǎo)致渲染引擎崩潰,多進(jìn)程架構(gòu)使得每一個(gè)渲染引擎運(yùn)行在各自的進(jìn)程中,相互之間不受影響,也就是說,當(dāng)其中一個(gè)頁面崩潰掛掉之后,其他頁面還可以正常的運(yùn)行不收影響。

          第二,更高的安全性和沙盒性(sanboxing)。渲染引擎會(huì)經(jīng)常性的在網(wǎng)絡(luò)上遇到不可信、甚至是惡意的代碼,它們會(huì)利用這些漏洞在你的電腦上安裝惡意的軟件,針對(duì)這一問題,瀏覽器對(duì)不同進(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,就會(huì)有一個(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)程模式會(huì)對(duì) 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

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

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

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

          默認(rèn)模式選擇

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

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

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

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

          網(wǎng)頁加載過程

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

          第一步:處理輸入

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

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

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

          第三步:讀取響應(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 文件或者其它文件,會(huì)把相關(guān)數(shù)據(jù)傳輸給下載管理器。

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

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

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

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

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

          到了這一步,數(shù)據(jù)和渲染進(jìn)程都準(zhǔn)備好了,Browser Process?會(huì)向?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ū)Ш綑跁?huì)更新,安全指示符更新(地址前面的小鎖),訪問歷史列表(history tab)更新,即可以通過前進(jìn)后退來切換該頁面。

          第六步:初始化加載完成

          當(dāng)導(dǎo)航提交完成后,渲染進(jìn)程開始加載資源及渲染頁面(詳細(xì)內(nèi)容下文介紹),當(dāng)頁面渲染完成后(頁面及內(nèi)部的iframe都觸發(fā)了onload事件),會(huì)向?yàn)g覽器進(jìn)程發(fā)送IPC消息,告知瀏覽器進(jìn)程,這個(gè)時(shí)候UI thread會(huì)停止展示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)程中,包含線程分別是:

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

          構(gòu)建DOM

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

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

          資源子加載

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

          JavaScript的下載與執(zhí)行

          構(gòu)建DOM過程中,如果遇到

          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                    <th id="afajh"><progress id="afajh"></progress></th>
                    西西WWW444大胆视频 | 在线观看成年人视频 | 亚洲特级毛片精品久久 | 免费一级黄色片子 | 熟女人妻-X88AV |