《深入理解Android》一2.1 浏览器工作原理概述
本節(jié)書摘來自華章出版社《深入理解Android》一書中的第2章,第2.1節(jié),作者孟德國 王耀龍 周金利 黎歡,更多章節(jié)內(nèi)容可以訪問云棲社區(qū)“華章計(jì)算機(jī)”公眾號(hào)查看
2.1 瀏覽器工作原理概述
眾所周知,萬維網(wǎng)(World Wide Web,WWW)以統(tǒng)一資源定位符(Uniform Resource Locator,URL)作為地址空間編碼,以超文本傳送協(xié)議(HyperText Transfer Protocol,HTTP)請(qǐng)求和應(yīng)答,以超文本標(biāo)記語言(HyperText Markup Language,HTML)記錄并以超鏈接(hyperlink)互相關(guān)聯(lián)起來的網(wǎng)頁(web page)文檔作為內(nèi)容單元,構(gòu)成了人類有史以來最為龐大的資料信息庫。瀏覽器(browser application)即是專門用來訪問和瀏覽萬維網(wǎng)頁面的客戶端軟件,也是現(xiàn)代計(jì)算機(jī)系統(tǒng)中應(yīng)用最為廣泛的軟件之一,其重要性不言而喻。瀏覽器內(nèi)部最主要也是最重要的模塊是負(fù)責(zé)頁面渲染的排版引擎(layout engine),也可稱作瀏覽器的內(nèi)核(kernel),其余的部分可統(tǒng)稱為瀏覽器的外殼(browser shell)。
下面將從頁面、排版引擎和瀏覽器外殼應(yīng)用三個(gè)方面對(duì)萬維網(wǎng)和瀏覽器技術(shù)的基本概念和原理逐一地做簡(jiǎn)單介紹。
2.1.1 頁面
現(xiàn)代Web Page通常由三部分組成:描述頁面結(jié)構(gòu)和內(nèi)容的HTML語言,控制頁面動(dòng)態(tài)邏輯的JavaScript腳本,設(shè)定頁面風(fēng)格樣式的層疊樣式表(Cascading Style Sheets,CSS)。
HTML是為創(chuàng)建和描述可在瀏覽器中展現(xiàn)的網(wǎng)頁信息而設(shè)計(jì)的一種文本格式標(biāo)記語言,最初于1982年由Tim Berners-Lee創(chuàng)建,后來成為國際標(biāo)準(zhǔn),由萬維網(wǎng)聯(lián)盟(W3C)維護(hù)。HTML由SGML(Standard Generalized Markup Language)簡(jiǎn)化發(fā)展而來,能夠結(jié)構(gòu)化地表示文檔的構(gòu)成和內(nèi)容(如標(biāo)題、段落、文本、表格),以及一定的外觀(如寬、高、顏色)和語義(如注釋、鏈接)。HTML頁面由多種尖括號(hào)<>包圍起來的標(biāo)簽元素以樹形結(jié)構(gòu)組成,其頂級(jí)標(biāo)簽為,內(nèi)容標(biāo)簽為
JavaScript是一種內(nèi)置于瀏覽器的動(dòng)態(tài)、弱類型、基于原型的網(wǎng)頁腳本語言。一般來說,完整的JavaScript應(yīng)該包括以下幾個(gè)部分:
ECMAScript:描述了該語言的語法和基本對(duì)象;
文檔對(duì)象模型(DOM):描述處理網(wǎng)頁內(nèi)容的方法和接口;
瀏覽器對(duì)象模型(BOM):描述與瀏覽器進(jìn)行交互的方法和接口。
JavaScript的出現(xiàn)使得網(wǎng)頁由單純的靜態(tài)HTML變成動(dòng)態(tài)可編程的DHTML,開發(fā)者可用JavaScript來完成讀寫DOM,向頁面添加交互行為,對(duì)瀏覽器事件做出響應(yīng),創(chuàng)建和發(fā)起網(wǎng)絡(luò)請(qǐng)求等許多工作。
層疊樣式表(CSS)的發(fā)明是為了將網(wǎng)頁的內(nèi)容描述與顯示風(fēng)格的描述分隔出來,HTML中只包含結(jié)構(gòu)和內(nèi)容的描述信息,CSS則只包含樣式的描述信息。單獨(dú)把一些顯示風(fēng)格信息如字體顏色、背景、排版方式等統(tǒng)一放在CSS文本中,可以大大簡(jiǎn)化HTML文件,同時(shí)增強(qiáng)可讀性和修改靈活性。
Web Page一般由前端(front end)開發(fā)設(shè)計(jì)人員直接編寫或者由服務(wù)器端的腳本動(dòng)態(tài)生成,通過Web服務(wù)器以HTTP協(xié)議發(fā)布,供瀏覽器訪問,這種方式即是通常所說的B/S架構(gòu)(Browser/Server Architecture)。
2.1.2 內(nèi)核
瀏覽器的內(nèi)核或稱排版引擎,負(fù)責(zé)請(qǐng)求網(wǎng)絡(luò)頁面資源加以解析排版并呈現(xiàn)給用戶。從資源的下載到最終的頁面展現(xiàn),可簡(jiǎn)單地理解成一個(gè)線性串聯(lián)的變換過程的組合,原始輸入為URL地址,最終輸出為頁面Bitmap,中間依次經(jīng)過了Loader、Parser、Layout和Paint模塊,如圖2-1所示。
Loader模塊(如圖2-2所示)負(fù)責(zé)處理所有的HTTP請(qǐng)求以及網(wǎng)絡(luò)資源的緩存,相當(dāng)于是從URL輸入到Page Resource輸出的變換過程。HTML頁面中通常有外鏈的JS/CSS/Image資源,為了不阻塞后續(xù)解析過程,一般會(huì)有兩個(gè)IO管道同時(shí)存在,一個(gè)負(fù)責(zé)主頁面下載,一個(gè)負(fù)責(zé)各種外鏈資源的下載。
雖然大部分情況下不同資源可以并發(fā)下載異步解析(如圖片資源可以在主頁面解析顯示完成后再被顯示),但JS腳本可能會(huì)要求改變頁面,因此有時(shí)保持執(zhí)行順序和下載管道后續(xù)處理的阻塞是不可避免的。
Parser模塊主要負(fù)責(zé)解析HTML頁面,完成從HTML文本到HTML語法樹再到文檔對(duì)象樹(Document Object Model Tree,DOM Tree)的映射過程。
HTML語法樹生成如圖2-3所示是一個(gè)典型的語法解析過程,可以分成兩個(gè)子過程:詞法解析和語法解析。詞法解析按照詞法規(guī)則(如正則表達(dá)式)將HTML文本分割成大量的標(biāo)記(token),并去除其中無關(guān)的字符如空格。語法解析按照語法規(guī)則(如上下文無關(guān)文法)匹配Token序列生成語法樹,通常有自上而下和自下而上兩種匹配方式。
瀏覽器內(nèi)核中對(duì)HTML頁面真正的內(nèi)部表示并不是語法樹,而是W3C組織規(guī)范的文檔對(duì)象模型 (Document Object Model,DOM)。DOM也是樹形結(jié)構(gòu),以Document對(duì)象為根。DOM節(jié)點(diǎn)基本和HTML語法樹節(jié)點(diǎn)一一對(duì)應(yīng),因此在語法解析過程中,通常直接生成最終的DOM樹。下面這個(gè)HTML文檔對(duì)應(yīng)的語法樹如圖2-4所示,而實(shí)際構(gòu)建的DOM樹如圖2-5所示。
不同的頁面標(biāo)簽對(duì)應(yīng)不同類型的DOM樹節(jié)點(diǎn),如
標(biāo)簽會(huì)對(duì)應(yīng)HTMLDiv-Element。DOM節(jié)點(diǎn)類型構(gòu)成一個(gè)繼承體系,詳情可參見WebKit源碼中WebCore/dom和WebCore/html兩個(gè)目錄。頁面中所有的CSS由樣式表CSSStyleSheet集合構(gòu)成,而CSSStyleSheet是一系列CSSRule的集合,每一條CSSRule則由選擇器CSSStyleSelector部分和聲明CSSStyleDeclaration部分構(gòu)成,而CSSStyleDeclaration是CSS屬性和值的Key-Value集合。圖2-6顯示了某一CSS樣式表經(jīng)過CSSParser解析后在瀏覽內(nèi)核中的基本表示。
CSS解析完畢后會(huì)進(jìn)行CSSRule的匹配過程,即尋找滿足每條CSS規(guī)則Selector部分的HTML元素,然后將其Declaration部分應(yīng)用于該元素。實(shí)際的規(guī)則匹配過程會(huì)考慮到默認(rèn)和繼承的CSS屬性、匹配的效率及規(guī)則的優(yōu)先級(jí)等因素。
JavaScript一般由單獨(dú)的腳本引擎解析執(zhí)行,它的作用通常是動(dòng)態(tài)地改變DOM樹(比如為DOM節(jié)點(diǎn)添加事件響應(yīng)處理函數(shù)),即根據(jù)時(shí)間(timer)或事件(event)映射一棵DOM樹到另一棵DOM樹。
簡(jiǎn)單來說,經(jīng)過了Parser模塊的處理,內(nèi)核把頁面文本轉(zhuǎn)換成了一棵節(jié)點(diǎn)帶CSS Style、會(huì)響應(yīng)自定義事件的Styled DOM樹。
顧名思義,Layout過程就是排版,它包含兩大過程。
步驟1:創(chuàng)建布局樹。
布局樹(或者叫做渲染樹、Render Tree,如圖2-7所示)和DOM樹大體能一一對(duì)應(yīng),兩者在內(nèi)核中同時(shí)存在但作用不同。DOM樹是HTML文檔的對(duì)象表示,同時(shí)也作為JavaScript操縱HTML的對(duì)象接口。Render樹是DOM樹的排版表示,用以計(jì)算可視DOM節(jié)點(diǎn)的布局信息(如寬、高、坐標(biāo))和后續(xù)階段的繪制顯示。
并非所有DOM節(jié)點(diǎn)都可視,也就是并非所有DOM樹節(jié)點(diǎn)都會(huì)對(duì)應(yīng)生成一個(gè)Render樹節(jié)點(diǎn)。例如,
步驟2:計(jì)算布局。
布局就是安排和計(jì)算頁面中每個(gè)元素大小位置等幾何信息的過程。HTML 采用流式布局模型,基本的原則是頁面元素在順序遍歷過程中依次按從左至右、從上至下的排列方式確定各自的位置區(qū)域。一個(gè)HTML元素對(duì)應(yīng)一個(gè)以CSS盒子模型(如圖2-8所示)描述的方塊區(qū)域,盒子模型決定了內(nèi)容、邊框和邊框內(nèi)外填充區(qū)(Padding、Margin)的大小。HTML元素分成兩個(gè)基本類型,Inline和Block。Inline元素不會(huì)換行,按從左到右來布局。Block元素的出現(xiàn)意味著需要從上至下?lián)Q到下一行來布局。除了這種基本的順序按照元素的Inline和Block來進(jìn)行流式布局之外,還有特殊指定的一些布局方式,如Absolute/Fixed/Relative三種定位布局以及Float浮動(dòng)布局。簡(jiǎn)單情況下,布局可以順序遍歷一次Render樹完成,但也有需要迭代的情況。當(dāng)祖先元素的大小位置依賴于后代元素或者互相依賴時(shí),一次遍歷就無法完成布局,如Table元素的寬高未明確指定而其下某一子元素Tr指定其高度為父Table高度的30%的情況。
經(jīng)過了Layout階段的處理,我們把帶Style的DOM樹變換成包含布局信息和繪制信息的Render樹,接下來的顯示工作就交由Paint模塊進(jìn)行操作了。
Paint模塊負(fù)責(zé)將Render樹映射成可視的圖形,它會(huì)遍歷Render樹調(diào)用每個(gè)Render節(jié)點(diǎn)的繪制方法將其內(nèi)容顯示在一塊畫布或者位圖上,并最終呈現(xiàn)在瀏覽器應(yīng)用窗口中成為用戶看到的實(shí)際頁面。每個(gè)節(jié)點(diǎn)對(duì)應(yīng)的大小位置等信息都已經(jīng)由Layout階段計(jì)算好了,節(jié)點(diǎn)的內(nèi)容取決于對(duì)應(yīng)的HTML元素,或是文本,或是圖片,或是UI控件。
通常情況下,布局和繪制是相當(dāng)耗時(shí)的操作。如果DOM樹每次略有改動(dòng)都要重新布局和繪制一次,效率會(huì)相當(dāng)?shù)拖隆R虼?#xff0c;一般瀏覽內(nèi)核都會(huì)實(shí)現(xiàn)一種增量布局和增量繪制的方式。當(dāng)一個(gè)DOM樹節(jié)點(diǎn)(或者它的子節(jié)點(diǎn))內(nèi)容或者樣式發(fā)生變化時(shí),內(nèi)核會(huì)確定其影響范圍,在布局階段會(huì)標(biāo)記出受該節(jié)點(diǎn)布局影響的其他節(jié)點(diǎn)(比如可能是子節(jié)點(diǎn)),在繪制階段則會(huì)標(biāo)記出一個(gè)Dirty區(qū)域并通知系統(tǒng)重繪。
按照HTML相關(guān)規(guī)范,頁面元素的CSS屬性也規(guī)定了其繪制順序,如根據(jù)不同Layer必須按順序繪制,否則覆蓋疊加效果會(huì)出現(xiàn)錯(cuò)誤,如元素的邊框輪廓和內(nèi)容背景的繪制次序也有規(guī)定。
基本上瀏覽內(nèi)核的工作原理即如上所述,不同瀏覽器的具體實(shí)現(xiàn)架構(gòu)不盡相同,所采用的術(shù)語名稱可能不一樣,但都需要完成上述各個(gè)階段的工作。例如,Mozilla Firefox瀏覽器使用的Gecko排版引擎主要流程如圖2-9所示。
2.1.3 外殼
瀏覽器作為一個(gè)完整軟件,除了對(duì)用戶透明和不可見的渲染引擎作為內(nèi)核外,還需要有供用戶交互使用的外殼UI界面,圖2-10給出了一個(gè)瀏覽器Shell的基本模塊架構(gòu)。目前的主流瀏覽器基本都會(huì)提供如下功能:
地址欄URI輸入;
前進(jìn)后退和刷新停止的控制按鈕;
主頁、網(wǎng)絡(luò)導(dǎo)航和搜索;
歷史、書簽和下載管理;
多標(biāo)簽頁瀏覽和會(huì)話管理;
查找、縮放和全屏;
數(shù)據(jù)持久化如Cookie、LocalStorage等;
選項(xiàng)設(shè)置;
插件和功能擴(kuò)展。
由于Ajax、HTML 5等前端技術(shù)和瀏覽引擎的迅猛發(fā)展,今天的瀏覽器已經(jīng)超出了展現(xiàn)某URL上網(wǎng)頁內(nèi)容這一基本功能的范疇,網(wǎng)頁可作為繪圖、辦公、游戲、即時(shí)通信等應(yīng)用的載體。Web App已經(jīng)成為現(xiàn)實(shí),瀏覽器也從單一的工具軟件向Web OS的方向演進(jìn)。每一個(gè)Web Page或Web App可看成對(duì)應(yīng)于傳統(tǒng)操作系統(tǒng)中的一個(gè)Native App,排版引擎作為Kernel執(zhí)行Web App,瀏覽外殼作為GUI Shell供用戶操作使用,多標(biāo)簽瀏覽器相當(dāng)于多任務(wù)操作系統(tǒng),Google的Chrome瀏覽器和由此演變而來的Chrome OS可看作這一想法的實(shí)施典型。圖2-11描述了Chrome瀏覽器和WebKit排版引擎之間的層次結(jié)構(gòu)和調(diào)用關(guān)系,圖2-12則給出了Chrome多進(jìn)程設(shè)計(jì)的核心架構(gòu)。
總結(jié)
以上是生活随笔為你收集整理的《深入理解Android》一2.1 浏览器工作原理概述的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 线性规划问题(一)
- 下一篇: 《Java和Android开发实战详解》