崔滔
Web瀏覽器無(wú)疑是用戶(hù)訪(fǎng)問(wèn)互聯(lián)網(wǎng)很常見(jiàn)的入口,其借免安裝和跨平臺(tái)等優(yōu)勢(shì),逐漸取代了很多傳統(tǒng)的客戶(hù)端。
Web瀏覽器通過(guò)向URL發(fā)送網(wǎng)絡(luò)請(qǐng)求來(lái)訪(fǎng)問(wèn)Web服務(wù)器資源,并以交互性的方式展示這些內(nèi)容?;静僮靼ǐ@取、處理、顯示和存儲(chǔ),常見(jiàn)的瀏覽器包括Internet Explorer,F(xiàn)irefox,Chrome,Safari,Opera等。
用戶(hù)界面
這是用戶(hù)與瀏覽器發(fā)生交互的區(qū)域。瀏覽器的外觀(guān)沒(méi)有特定的標(biāo)準(zhǔn),HTML5規(guī)范沒(méi)有規(guī)定UI元素該長(zhǎng)什么樣,但是列出了一些常見(jiàn)元素:地址欄、個(gè)人信息欄、滾動(dòng)條、狀態(tài)欄和工具欄等。
瀏覽器引擎
它提供了UI與底層渲染引擎之間的接口,根據(jù)用戶(hù)交互進(jìn)行查詢(xún)和操控渲染引擎,提供初始化加載URL的方法,并負(fù)責(zé)重新加載、返回和前進(jìn)等操作。
渲染引擎
渲染引擎負(fù)責(zé)在屏幕上顯示網(wǎng)頁(yè)內(nèi)容,其主要工作是解析HTML。渲染引擎默認(rèn)可展示HTML、XML和圖片,還可以通過(guò)插件或擴(kuò)展程序支持其他數(shù)據(jù)類(lèi)型。
Web內(nèi)容渲染過(guò)程大致如下:
HTML數(shù)據(jù)轉(zhuǎn)成DOM
來(lái)自網(wǎng)絡(luò)層的請(qǐng)求內(nèi)容在渲染引擎中接收(通常是8 KB的塊),然后將原始字節(jié)轉(zhuǎn)換為HTML文件中的字符(基于字符編碼)。接著詞法分析器進(jìn)行詞法分析,將輸入分解為各種標(biāo)記(token),在標(biāo)記化過(guò)程中,文件中的每個(gè)開(kāi)始和結(jié)束標(biāo)簽都被記錄下來(lái)。它知道如何去掉不相關(guān)的字符,比如空格和換行符。
接著,解析器進(jìn)行語(yǔ)法分析,通過(guò)分析文檔結(jié)構(gòu),應(yīng)用語(yǔ)言語(yǔ)法規(guī)則構(gòu)造解析樹(shù)。解析過(guò)程是迭代進(jìn)行的,它向詞法分析器請(qǐng)求新的token,如果匹配語(yǔ)法規(guī)則,token就被添加到解析樹(shù)中,然后再請(qǐng)求另一個(gè)token。如果沒(méi)有匹配的規(guī)則,解析器將在內(nèi)部存儲(chǔ)token,并不斷請(qǐng)求新token,直到找到匹配所有內(nèi)部存儲(chǔ)token的規(guī)則。如果沒(méi)有找到規(guī)則,解析器將拋出異常,說(shuō)明文檔無(wú)效或包含語(yǔ)法錯(cuò)誤。
這些節(jié)點(diǎn)在文檔對(duì)象模型(DOM)樹(shù)數(shù)據(jù)結(jié)構(gòu)中互相鏈接,建立父子關(guān)系、相鄰兄弟關(guān)系。
CSS數(shù)據(jù)轉(zhuǎn)成CSSOM
CSS數(shù)據(jù)原始字節(jié)被轉(zhuǎn)換成字符、token和節(jié)點(diǎn),最終變成CSS對(duì)象模型(CSSOM)。CSS的層級(jí)特性決定了元素會(huì)應(yīng)用什么樣式。元素的樣式數(shù)據(jù)可以來(lái)自父元素(通過(guò)繼承),也可以直接在元素上設(shè)置。瀏覽器需要遞歸遍歷CSS樹(shù)結(jié)構(gòu)來(lái)確定特定元素的樣式。
DOM與CSSOM組成渲染樹(shù)
DOM樹(shù)包含了HTML元素之間的關(guān)系信息,CSSOM樹(shù)則包含了這些元素的樣式信息。從根節(jié)點(diǎn)開(kāi)始,瀏覽器會(huì)遍歷每一個(gè)可見(jiàn)節(jié)點(diǎn),有些節(jié)點(diǎn)是隱藏的(通過(guò)CSS控制),不會(huì)出現(xiàn)在渲染結(jié)果中。對(duì)于每個(gè)可見(jiàn)節(jié)點(diǎn),瀏覽器找到CSSOM中定義的相關(guān)規(guī)則進(jìn)行匹配,最終這些節(jié)點(diǎn)會(huì)帶著內(nèi)容和樣式出現(xiàn)在渲染樹(shù)中。
布局
接下來(lái)進(jìn)行內(nèi)容布局。內(nèi)容的實(shí)際尺寸和位置需要經(jīng)過(guò)計(jì)算才能渲染到頁(yè)面上,這個(gè)過(guò)程也叫重排(reflow)。HTML采用基于流的布局模型,也就是說(shuō)大部分情況下,幾何位置是一次性計(jì)算出來(lái)的(內(nèi)容大小或位置發(fā)生變化,需要重新計(jì)算)。這個(gè)過(guò)程是從文檔根元素開(kāi)始,遞歸完成的。
繪制
通過(guò)遍歷每個(gè)渲染器,并調(diào)用paint方法在屏幕上顯示內(nèi)容。繪制過(guò)程可以是全局的(繪制整個(gè)樹(shù)),也可以是增量的(渲染樹(shù)在屏幕上驗(yàn)證某個(gè)矩形區(qū)域),操作系統(tǒng)在這些特定節(jié)點(diǎn)上生成繪制事件,整個(gè)樹(shù)不受影響。繪制是一個(gè)漸進(jìn)的過(guò)程,其中一部分在被解析和渲染過(guò)后,而該過(guò)程將繼續(xù)處理其余部分。
JavaScript解析器(JS引擎)
JavaScript是一種腳本語(yǔ)言,可動(dòng)態(tài)更新Web內(nèi)容、控制多媒體和動(dòng)畫(huà)等,這些是通過(guò)瀏覽器的JS引擎完成的。DOM和CSSOM提供了JS接口,都可以通過(guò)JS修改,由于瀏覽器不確定某些JS會(huì)做什么,因此它會(huì)在遇到script標(biāo)簽后會(huì)立即暫停構(gòu)建DOM樹(shù)。
JS解析器在接收到服務(wù)器發(fā)送來(lái)的代碼后,會(huì)立即進(jìn)行解析,代碼被轉(zhuǎn)換成機(jī)器能理解的對(duì)象表示形式。保存了所有解析信息的對(duì)象叫做抽象語(yǔ)法樹(shù)(AST),這些對(duì)象又被解析器轉(zhuǎn)換成字節(jié)碼。這種編譯方式叫做(Just In Time,JITs),也就是Java Script從服務(wù)器下載后在客戶(hù)端實(shí)時(shí)編譯。解析器和編譯器是組合使用的,解析器立即處理源代碼,編譯器則生成機(jī)器碼,客戶(hù)端操作系統(tǒng)可直接運(yùn)行。
UI Back End用于繪制基礎(chǔ)控件,比如復(fù)選框和窗口等。底層使用操作系統(tǒng)的用戶(hù)界面方法,暴露通用的接口,跟平臺(tái)無(wú)關(guān)。
數(shù)據(jù)存儲(chǔ)層
這是持久化層,輔助瀏覽器保存一些數(shù)據(jù)(比如cookies,session storage,indexed DB,Web SQL和書(shū)簽以及用戶(hù)的偏好設(shè)置等)。HTML5規(guī)范提出了瀏覽器端的完整數(shù)據(jù)庫(kù)功能。
網(wǎng)絡(luò)層
這一層處理瀏覽器的各種網(wǎng)絡(luò)通信,瀏覽器使用各種通信協(xié)議獲取網(wǎng)絡(luò)資源,比如HTTP,HTTPs,F(xiàn)TP等。
瀏覽器用DNS解析URL,這些解析記錄緩存在瀏覽器、操作系統(tǒng)、路由器或者ISP中。如果請(qǐng)求的URL不在緩存中, ISP的DNS服務(wù)器首先發(fā)起DNS查詢(xún),找到正確的IP地址后,瀏覽器使用特定的協(xié)議與服務(wù)器建立連接。瀏覽器向服務(wù)器發(fā)送SYN數(shù)據(jù)包,詢(xún)問(wèn)服務(wù)器是否打開(kāi)了TCP連接,服務(wù)器用SYN/ACK數(shù)據(jù)包響應(yīng)作為前面SYN的應(yīng)答,瀏覽器接收到應(yīng)答后,再向服務(wù)器發(fā)送ACK數(shù)據(jù)包。通過(guò)這樣的3次握手就建立了TCP連接,一旦建立了連接,就可以傳輸數(shù)據(jù)了。傳輸數(shù)據(jù)過(guò)程中必須遵守HTTP協(xié)議的相關(guān)要求,包括請(qǐng)求和響應(yīng)的規(guī)則等。
瀏覽器比較
如今市面上有各種不同的瀏覽器,盡管核心功能都是相同的,但是它們之間的區(qū)別也是多方面的。包括平臺(tái)(Linux,Windows,Mac,BSD以及其他Unix系統(tǒng))、協(xié)議、用戶(hù)界面、HTML5支持情況、是否開(kāi)源和所有權(quán)等。