WEB前端底层知识--浏览器是如何工作的
隨筆- 6? 文章- 2? 評論- 103?
?
?
WEB前端底層知識--瀏覽器是如何工作的
概述
???? 對于一直從事B/S架構(B/S也是一種C/S架構,只不過C/S自己寫顯示而B/S有相對統一的顯示引擎實現而已)WEB領域的開發人員來說,瀏覽器Browser再熟悉不過了。不管你是JAVA流還是微軟流抑或PHP流,WEB開發新流派。不論你的服務器端采用哪種業務架構,ORACLE數據庫還是MSSQL,站在用戶的角度思考,這個才是他們直接能接觸到的,前端的用戶體驗給了用戶直觀的印象,投其所好,我們也總少不了要跟它打交道,很多問題的根源皆來源于此,了解一下其內部執行原理,也許對我們的開發工作會事半功倍,從一位純粹的開發人員到一位技術領域的專家,也許就在于這些細節中。
本文討論僅限HTML/CSS類與瀏覽器顯示相關的知識。
不包括javascript瀏覽器引擎。
不包括客戶端與服務器端HTTP通信。
不包括服務器端處理流程部分。
瀏覽器種類
我們現在經常使用的主要有5種瀏覽器,Internet Explorer,Firefox,Safari,Chrome跟Opera,包含了市面上3種主流的瀏覽器網頁排版引擎,WebKi(chrome,safari,opera),Gecko(Mozilla,Firefox 等使用的排版引擎)和Trident(也稱為MSHTML,IE 使用的排版引擎)。(詳見http://www.cnblogs.com/liuzijing688/archive/2008/05/18/1201755.html),大家可以跑一下您所使用的瀏覽器跑分情況http://html5test.com/。其中Firefox,Chrome ,Safari三款瀏覽器部分源代碼是開源的,一些分析工作正式基于其源碼進行的分析。順便說一句, Chrome等開源瀏覽器市場中所占的份額越來越高(見http://www.w3schools.com/browsers/browsers_stats.asp)(ie6使用情況http://www.ie6countdown.com/), HTML5前端開發利器的推出,HTML支持標準的逐漸統一,IE6(7,8)等低版本的逐漸淘汰,也許往后針對CSS HACK等兼容性場景的需求會越來越少,專注于實現而不是專注于兼容,提高我們的效率,體現思想核心價值體現,這才是開發人員真正該干的事。站在用戶的角度來思考,只是稍微改變一下操作方式換來的是真正的產品易用性與安全性的提升,也是一件好事,希望往后的產品開發都只針對IE9以上版本。
瀏覽器的主要職責
瀏覽器,我們天天在用,可是如果哪天面試一個WEB領域的開發,要你說出他的職責,未必人人都能一下子清楚的表述出來。我覺得瀏覽器的首要功能就是把用戶想要的各種形式WEB資源確認無誤的顯示出來,通常我們見到的資源格式主要是HTML,當然還包括PDF,圖片,視頻等,資源的定位通過URI來實現(Uniform resource Identifier)。
W3C (World Wide Web Consortium) 組織制定了一套HTML/CSS規范,清楚的描述了瀏覽器如何解釋HTML文件以及如何去顯示它,W3C 也是WEB領域標準協議的制定組織。目前我們常見的HTML主要為? HTML4.01跟XHTML1.0,由1999年推出(http://www.w3.org/TR/html401/)。 HTML5 規范現在仍處于發展階段,雖然已接近尾聲且各大主流瀏覽器都有所支持,但仍不是很完善。目前CSS也主要是CSS2.0((http://www.w3.org/TR/CSS2/),??? 隨著時間的推移,硬件的發展,軟件行業的進步,HTML5/CSS3黃金組合一定會流行起來的。同樣,CSS版本3進行中。以前的瀏覽器市場是百花爭艷,百家齊鳴,往往只支持大部分的規范內容同時還在發展各自的拓展,這對于WEB開發人員和最終用戶來說帶來了嚴重的兼容性問題。幸好,現如今大多數的瀏覽器漸漸的修正了這一錯誤行為。
各大瀏覽器之間有很多共同點,其中公共的界面元素有:
從瀏覽器界面上來看,沒有相關的規范竟然能做到如此的一致,確實很奇怪。這正是各大瀏覽器廠商多年來相互的模仿導致的。HTML5協議并未約束瀏覽器要有哪些界面元素,只是列出了一些常用的,比如地址欄,狀態欄,工具欄。當然各瀏覽器都有一些各自的特性,如firefox的下載管理器。更多的介紹起參見以后的Browser User interface(瀏覽器界面元素)章節,此處不再累牘。
上面說了我們看到的瀏覽器大體情況,接下來再談談瀏覽器的主要組件有哪些,相互間的關系是怎樣的。
瀏覽器的基礎架構
需要注意的是,與其它瀏覽器不同chrome使用多個渲染引擎實例,每個Tab頁一個,即每個Tab都是一個獨立進程。
渲染過程
???? 用戶請求的HTML文本(text/html)通過瀏覽器的網絡層到達渲染引擎后,渲染工作開始。每次渲染文檔通常不會超過8K的數據塊,其中基礎的渲染流程圖如下:???????
詳細流程圖
渲染引擎首先解析HTML文檔,轉換為一棵DOM樹,此為第一步。接下來不管是內聯式,外聯式還是嵌入式引入的CSS樣式也會被解析,同時生成另外一棵用于渲染DOM樹的樹-渲染樹(render tree) ,渲染樹包含帶有顏色,尺寸等顯示屬性的矩形,這些矩形的順序與顯示順序基本一致。然后就是對渲染樹的每個節點進行布局處理,確定其在屏幕上的顯示位置。最后就是遍歷渲染樹并用上一章提到的UI后端層將每一個節點繪制出來。
以上步驟是一個漸進的過程,為了提高用戶體驗,渲染引擎試圖盡可能快的把結果顯示給最終用戶。它不會等到所有HTML都被解析完才創建并布局渲染樹。它會在從網絡層獲取文檔內容的同時把已經接收到的局部內容先展示出來。
DOM樹
DOM對于前端JAVASCRIPT開發人員來說也許再熟悉不過了,DOM全稱為Document Object Model,即我們所說的文檔對象模型。我們可以把它看做是HTML元素對外的接口,有了這些接口javascript開發人員才能夠實現復雜的頁面功能。DOM樹的根節點是Document對象。DOM也是有規范的,可見?http://www.w3.org/DOM/DOMTR。與XML解析器不同的是,HTML相對來說比較寬松,即使不標準的書寫方式也會解析出來,不會拋出解析異常之類的錯誤。
瀏覽器利用HTML解析器,分析接收到的HTML文本構件出dom object添加到dom樹相應位置上。解析的時候會利用DTD(Document Type Definition)規范描述,DTD中包含了所有允許的元素(element)以及這些元素的屬性(attribute),以及元素之間可能的層次關系。市面上我們看到很多類型的DTD,那是為了兼容以前的書寫的HTML文檔,目前標準推薦的DTD規范定義可見http://www.w3.org/TR/html4/strict.dtd,解析HTML正是基于此規范,上頭列舉了支持的元素類型,元素的屬性以及事件等信息。
所有HTML引用的外部資源默認都是異步加載的,即解析與下載資源同時進行,但由于腳本資源(.js)在解析過程中就有可能運行,如document.write之類的,所以默認腳本資源加載的時候是同步進行的,除非添加了defer或者asyn之類的屬性。CSS由于不會更改DOM對象的結構,其資源的加載是異步的。這樣就又會產生一個問題,譬如<link href=a.css> 然后<script src=a.js>,a.js可能用到了a.css里頭定義的class,但是由于a.css加載是異步的,a.js卻是同步執行的,可能就會報錯,遇到這種情況,瀏覽器會進行特殊處理,當加載腳本的時候如果當前還在加載樣式資源,則加載腳本的操作會被阻塞知道樣式文件加載完畢。
當以上解析過程完畢后,瀏覽器繼續進行標記為deferred模式的腳步解析,然后就是整個解析過程的實際結束。文檔狀態設置為complete,同時觸發load事件。
??? Render樹
??? 瀏覽器在構造DOM樹的同時也在構造著另一棵樹-Render Tree,與DOM樹相對應暫且叫它Render樹吧,我們知道DOM樹為javascript提供了一些列的訪問接口(DOM API),但這棵樹是不對外的。它的主要作用就是把HTML按照一定的布局與樣式顯示出來,用到了CSS的相關知識。從MVC的角度來說,可以將render樹看成是V,dom樹看成是M,C則是具體的調度者,比HTMLDocumentParser等。
Render樹的每一個節點我們叫它renderer,其由下列類型的基礎類構造。
?| class RenderObject{ ????virtual void layout(); ????virtual void paint(PaintInfo); ????virtual void rect repaintRect(); ????Node* node;? //the DOM node ????RenderStyle* style;? // the computed style ????RenderLayer* containgLayer; //the containing z-index layer } |
?
??? DOM樹與Render樹
???? 可以這么說,沒有DOM樹就沒有Render樹,但是它們之間可不是簡單的一對一的關系。我們已經知道了render樹是用于顯示的,那不可見的元素當然不會在這棵樹中出現了,譬如<head>,您還能想到哪些呢?除此之外,diplay等于none的也不會被顯示在這棵樹里頭,但是visibility等于hidden的元素是會顯示在這棵樹里頭的,可以自己想一下為什么。說了這么多render樹,我們還沒見一下它的真容呢,它到底會是個什么模樣呢?我們看一下圖。
??
與DOM對象類型很豐富啊,什么head,title,div,而Render樹相對來說就比較單一了,畢竟它的職責就是為了以后的顯示渲染用嘛。從上圖我們還可以看出,有些DOM元素沒有對應的renderer,而有些DOM元素卻對應了好幾個renderer,對應多個renderer的情況是普遍存在的,就是為了解決一個renderer描述不清楚如何顯示出來的問題,譬如select元素,我們就需要三個renderer,one for the display area, one for the drop down list box and one for the button。
上圖中還有一種關系未可看出,即renderer與dom元素的位置也可能是不一樣的。說的就是那些添加了float:---或者position:absolute的元素,因為它們脫離了正常的文檔流順序,構造Render樹的時候會針對它們實際的位置進行構造。
CSS樣式
樣式來源有下列三種方式
一個元素最終經過計算可能匹配到了很多條樣式規則,他們之間存在一定的優先順序,從低到高有:
樣式優先級計算公式
具體可見http://www.w3.org/TR/CSS2/cascade.html#specificity
??? 布局與顯示
??? 上面確定了renderer的樣式規則后,然后就是重要的顯示因素布局了。當renderer構造出來并添加到render樹上之后,它并沒有位置跟大小信息,為它確定這些信息的過程,我們就稱之為布局。
???? 從頁面開發角度說,拿到一個HTML頁面,明確了頁面要實現的功能之后,首先開始動手做的就是布局啦,其它譬如背景圖片,字體,文字啦之類的樣式問題還好說,布局卻是讓人有點感覺經常與其打交道卻經常的感覺駕馭不了它,至于界面邏輯或者交互設計雖然也比較難但是至少能讓人摸著頭腦,所以有必要細說一下這個布局。平時大家瀏覽網頁遇到好看的布局也一定要多花點時間去分析分析它,非前端開發人員多掌握一點界面設計或者交互設計之類的知識未嘗不是一件好事,更何況現在好多情況都是一套軟件產品從設計到出品整套制造過程都要參與,很有收縮性。
???? 瀏覽器進行頁面布局基本過程是以瀏覽器可見區域為畫布,左上角為(0,0)基礎坐標,從左到右,從上到下從DOM的根節點開始畫,首先確定顯示元素的大小跟位置,此過程是通過瀏覽器計算出來的,用戶CSS中定義的量未必就是瀏覽器實際采用的量,靈活的布局方式卻是靠經驗以及設計領域相關經驗等得來的。如果顯示元素有子元素得先去確定子元素的顯示信息,如果頁面布局完后有改動能不整體重新布局就不重新布局,當然由于腳本或者用戶操作也有可能隨時會被重新布局,那就回到了本段路起點。
?? 高度和寬度
???? 顯示元素的高度(height),寬度(width)的確定。元素的高度由子元素遍歷計算得來,而寬度由本身確定。
???? 最終所有顯示元素被構建成一個盒子類似的東西構成了整個布局效果,盒子模型效果圖如下:
?
???? Box Model詳細描述可見http://www.w3.org/TR/CSS2/box.html
? BOX TYPE
???? 每個顯示元素上還有一個重要屬性就是display及z-index,display不同的類型使用不同的渲染方式,即使沒有手動去指定它本身也會存在一個默認值,具體默認值情況請參見 http://www.w3.org/TR/CSS2/sample.html.
block類型的盒子具有自己的一塊區域,里頭養了很多inline box。各個block box按上下順序部件,各個inline box按從左到右順序布局,如果寬度不夠會自動換行。
定位方案,坐標值(left,top)
???? Normal--定位基于基本布局過程,從左到右,從上到下遞增實現。
???? Float--脫離正常文檔流,居最左或居最右。
???? Absolute--其位置信息由用戶指定。
有了size(width,height),position(left,top),box type(display:none,inline,block..e.t.c)一個顯示元素基本就最終確定了。
??? 布局完成后,瀏覽器將結果渲染出來,最終我們看到了眼前的頁面。
注:本文引用自http://www.cnblogs.com/mirror/archive/2013/04/05/3000517.html
轉載于:https://www.cnblogs.com/liuyu7177/archive/2013/04/24/3039598.html
總結
以上是生活随笔為你收集整理的WEB前端底层知识--浏览器是如何工作的的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 执行终端Ubuntu中-lz编译错误的解
- 下一篇: 301 重定向代码