瀏覽器端技術體系概覽 -- 前端開發的七種武器

科普文一則,說說我對前端技術體系(也稱瀏覽器端技術體系)的認識,希望能讓更多人瞭解前端,也希望能借此豐富前端開發的大局觀.

去年我寫了[url=http://limu.iteye.com/category/122180]網站性能優化[/url]系列文章,看過的朋友會知道,這類文章重點並非介紹各種具體的優化技巧,而是在關注發掘這些優化點的思路和方法.然後介紹給大家多種檢測手段去發現問題,進而有目標的解決問題.所有這些需要我們對有網頁整個生命週期有清晰的認識,對網頁中各種技術極其相互結合的方式有明確的認知.這就回歸到一個更本質的問題:瀏覽器端技術體系是怎樣的.

想用三言兩語說清前端技術不大可能,但是用一篇不長的文章說清何謂前端,還是可以做到的.因爲工作中我常會給後臺開發的同學介紹前臺技術,所以會經常涉及這類話題.

解析前端,我想需要回答如下幾個問題.
1.前端涉及幾種技術?分別是做什麼的?
2.在前端內部各種技術之間如何整合協作?
3.前端如何和後臺交流?

回答這些問題我會立即丟出前端開發的"七種武器"論,介紹前端主要涉及七種技術分別是什麼的同時,重點關注"七種武器"如何對內協作,如何對外交流.(鑑於本文的科普文性質,下面具體介紹中出現的"一切","都是","全部"這類定語可能並非絕對,但可以確定在99%的情況下是正確的)

[b]一.HTTP:網頁上的一切來自Http請求[/b]
頁面上所有內容都是通過若干Http請求從服務端加載而來.
第一個請求通常是一份(X)HTML文檔,也就是瀏覽器中地址欄的指向.如圖:
[img]http://dl.iteye.com/upload/attachment/454386/619b0260-bb61-3bf5-8308-3ca749fdb682.png[/img]
(這張圖可以通過Fixfox的Firebug插件,IE的Httpwatch工具,或者Chrome直接按Ctrl+Shift+I得到)
地址欄中的url通常會包含地址和一些參數,這樣就可以找到對應的後臺服務,同時讓其據這些動態參數來確定輸出內容.

多個Http請求之間是獨立的.那麼其他請求又是由誰觸發的呢?
由瀏覽器觸發!是在瀏覽器解析這第一份(X)HTML文檔的過程中發出,接下來我就將介紹這個過程.

[b]二.HTML:在瀏覽器中HTML被解析成DOM樹[/b]
HTML文檔是一份不那麼嚴謹的XML(文本)文檔.在任意網頁上點擊右鍵,點擊查看源代碼就可以看到.
瀏覽器按照HTML文檔內容自上而下的解析運行.最終HTML文本被完整的解析成一顆樹,稱DOM樹.
注意:DOM樹是瀏覽器內一切所依附的根本,是本文的重點,以後也會多次強調.
[img]http://dl.iteye.com/upload/attachment/454416/3883e54d-e85c-37c6-b915-5af1a90c03be.png[/img]
(這張圖可以通過Fixfox的Firebug插件,IE8/9按F12,或者Chrome直接按Ctrl+Shift+I找到)
繼續回答之前的問題:其餘的HTTP請求,除XHR(後面會介紹),CSS的@import和背景圖之外,幾乎都是在解析HTML時,由DOM樹上的幾種特定節點發起的.如圖中重點標示出的那些節點:
[*]<img>:用來嵌入圖片
[*]<iframe>:用來嵌套其他HTML
[*]<link>:可以用來引入CSS文件
[*]<script>:可以用來引入JavaScript文件
[*]<object>和<embed>:通常用來引入Flash文件
之所以強調這一點,一是它說明了HTML和Http的關係:首個Http載入HTML,解析HTML發起其他Http.二來再次強調了DOM樹,請求在HTML解析爲DOM樹過程中,在樹上節點被解析出來時觸發.

[b]三.CSS:使用CSS設定展現樣式和網頁佈局[/b]
如何定義網頁的樣式,比如字體的顏色和大小?這是CSS的工作.

<!--CSS出現之前,使用額外的樣式節點-->
<span><font size="50" color="red">文本</font></span>
<!--CSS,統一在節點的style屬性內定義-->
<span style="color:red,font-size:50px">文本</span>
<!--CSS,在節點之外統一定義,通過class,id等屬性關聯至節點-->
<span class="myTxt">文本</span>

我們看到最後一種方式,爲<span>節點指定了class屬性myTxt.而myTxt的詳細定義可以以兩種方式加入文檔.

<!--在style標籤內定義-->
<style>
.myTxt:{color:red,font-size:50px}
</style>
<!--通過<link>標籤引入額外的css,內部包含myTxt類的樣式定義-->
<link rel="stylesheet" type="text/css" href="http://a.com/a.css"/>

當然CSS的功能不止是簡單的樣式定義,還可以通過定義區塊的位置確定網頁佈局方式,CSS也自然有其一套語法,描述CSS的功能,以及確定CSS規則與DOM節點之間的關聯.這些細節並非本文重點.

我們看到CSS或者通過節點的style屬性,或者通過特定的<style><link>節點影響網頁,這又回到了我們反覆強調的內容,DOM樹,CSS並未脫離DOM樹,而是駐留其上.

[b]四.JavaScript:使用JavaScript處理交互事件[/b]
說到JavaScript,不如先澄清下"Java與JavaScript的關係是雷鋒與雷峯塔的關係".
網頁應用是典型的事件驅動GUI系統.JavaScript爲交互事件,時間線上的事件定義響應體.
我們看一個簡單的應用,點擊按鈕,彈出一個警告框.

<!--直接寫在onclick屬性中-->
<button onclick="alert(1)"></button>
<!--在onclick屬性中,調用test_clk方法-->
<button onclick="test_clk()"></button>
<!--在script標籤中,定義test_clk方法-->
<script>
function test_clk(){
alert(1);
}
</script>
<!--在script標籤引入外部js文件,內部包含test_clk方法的定義-->
<script src="http://a.com/a.js"></script>

接下來我們有個問題,js什麼時候運行?
[*]首先,當瀏覽器解析到<script>標籤時,開始運行其內的代碼.
[*]<script>標籤內代碼或者其他標籤內的特定屬性中可以定義事件響應體,在事件觸發時執行
[*]script代碼可以指定某些代碼在指定時長後開始執行,或每隔一定間隔重複執行

重要的是我們還是看到了,JS同樣沒有脫離DOM樹.同CSS一樣駐留DOM樹上.同時需要明確的是JS是被load到客戶端瀏覽器之後,在瀏覽器中運行的,消耗的是客戶端計算資源.JS爲瀏覽器端提供了計算能力,而瀏覽器端則是JS的宿主.JS作爲一種腳本語言,其實並不一定非要工作在瀏覽器這個宿主之上,但這脫離了前端技術體系,這裏不討論.

說到這裏,我們基本瞭解了構成一個獨立網頁的幾項要素,各自負責什麼,相互間如何協作.大家可能注意到,前面曾經說過每個http請求時相互獨立的,那麼如何讓各個網頁關聯起來呢?

首先網頁之間通過鏈接<a>或<form>表單關聯到一起.一般情況網頁之間通過點擊<a>形成一個新的執行a標籤href屬性的HttpGet請求,讓瀏覽器從一個頁面轉向另一個.

當需要瀏覽者通過客戶端提交數據時,我們通常製作一個表單,然後submit表單,將客戶數據將會通過HttpPost請求提交至另一個地址.

除此之外的另一個需求就是保持登陸狀態了,這需要一段信息始終在各個網頁間傳遞,但是放在url參數中顯然是不安全的.那如何實現這個功能?這正是接下來介紹的內容.

[b]五.Cookie:藉助Cookie標識瀏覽者身份,在頁面間保持會話[/b]
再次回到Http本身,它是一種無狀態的協議,分爲Header和Body兩部分,Body是http傳遞的主體內容,Header又分爲請求頭(RequestHeader)和(ResponseHeader)兩部分,而header中除了包含表明網頁間關係的參數之外也包含一些通用信息,頭當中的信息以鍵值對的方式書寫,主要負責通用的緩存策略描述和身份標識等功能,如圖:
[img]http://dl.iteye.com/upload/attachment/454471/3465d17c-8894-3f7a-a94d-d3cedd79a7ba.png[/img]
(這張圖,即爲第一張圖中某個http請求點開之後看到的詳情,需要注意圖中上面列出了響應頭,下面是請求頭,和發生順序不一致.firebug就是這個順序,注意區分)
服務端可以通過響應頭種植cookie到客戶端,而客戶端的每個請求的請求頭中都會攜帶域名下的cookie.比如這個到limu.iteye.com的請求,會包含iteye.com下的cookie,同時也包括limu.iteye.com的cookie.服務端可以通過cookie儲存會話id,這樣多個請求之間就有了關聯.同時服務端set cookie時指定cookie設置到哪兒域名及路徑下,以及在客戶端將駐留多久.

最後說一下JavaScript和Cookie的關係,JavaScript可以讀寫所在頁面域名下的cookie值.
需要注意在http://www.a.com下面引入了http://www.b.com/b.js,b.js能讀取所在頁面,也就是www.a.com以及a.com下的cookie,而非b.com下的cookie.而b.js這個http的請求頭中則帶有b.com系列的cookie,這個請求的響應頭中,也只能給b.com種植cookie.這裏有點繞,但有必要澄清,可以遇到問題的時候可以再仔細看.

到此爲止,我們瞭解了一個網頁的構成要素,也瞭解了網頁之間的聯繫,這樣我們就瞭解了一個傳統網站的前端技術體系.接下來我們介紹一些新花樣,正是這些帶來了Web2.0的前端變革.

[b]六.DHTML:使用JavaScript操作Dom樹[/b]
回到網頁之內,其實我們只是獲得了一顆DOM樹,其他內容都駐留在樹上.
接下來我們想一下,如果有一種手段能夠隨心所欲的改變動態這棵樹,那豈不是我們就在客戶端擁有了完全控制一個網頁的能力.這項能力自然由JavaScript承擔.
[img]http://dl.iteye.com/upload/attachment/454489/2807701d-8431-31b6-b0a7-ada5fedfa2e9.png[/img]
接下來設想一下,操作一個棵樹,也就是一份結構化的XML文檔我們需要怎樣的API?
[*]找到一個或一組葉子節點,從一個節點出發找到相關節點:父,子,兄弟.
[*]新增/複製節點,並插入到文檔中指定位置,以及刪除節點.
[*]增刪改葉子節點某個屬性以及節點包含的文本.
於是[url=http://www.w3.org/DOM/DOMTR]W3C(萬維網聯盟)的 DOM Level 1,2&3[/url]中定義了3個層次一系列Dom上的操作接口.其中Level1主要包含上面這些接口.在各種瀏覽器下Level 1基本都能被正確實現.

回憶一下,之前我們提到了JS的三個執行入口,很重要的一個是響應各種鼠標鍵盤事件,如何爲節點綁定事件響應動作,IE有獨特的事件模型.其餘瀏覽器的事件模型符合W3C DOM接口定義.

這一系列技術被稱爲D(Dynamic)HTML,其核心是通過JS將Http,HTML,CSS,JavaScript更好的粘合在一起.通過JavaScript可以改變網頁內的一切,甚至包括動態引入新的CSS和JS.
很酷是麼?但單獨DHTML並未流行起來,因爲我們空有力量卻不知道用到哪裏合適.於是當接下來介紹的技術被引入,當我們能夠根據服務端的指示來運用前臺的力量,一場影響深遠的真正的技術變革就此發生了.而在此之前,我們有必要意識到,DHTML不過是瀏覽器中JavaScript能力的一種擴展.

[b]七.Ajax:使用JavaScript在網頁內與服務器端交互[/b]
有了DHTML,JavaScript已經具有能力完全的改變所在網頁的每個細節.JavaScript的野心不止於此,如果JS能由事件驅動,從服務器端源源不斷的獲取新鮮數據,那理論上不再需要第二個頁面了.
我們再回憶下,網頁上一切來自HTTP,獲取數據自然需要JavaScript發起HTTP請求,並且可以讀懂這個Http請求響應內容.於是有了XHR(XmlHttpRequest),首先作爲一個ActiveX控件被IE5引入(這裏必須要感謝IE對不對?).
XHR就是這樣一個可以由JS發送Http請求,且當請求數據返回後將服務端數據交給JS的對象.而且XHR支持異步請求,在Http請求的過程中(因爲是和服務端打交道,所以這個操作耗時可能較長),頁面還可以正常工作,直到Http響應後會才觸發一個事件回調JS方法處理數據.
[img]http://dl.iteye.com/upload/attachment/454503/5720e2bf-63c0-354a-a161-2116e963b04d.png[/img]
如今Ajax並不單指XHR.所有在不離開當前頁面的前提下,由JS主動發起的從服務器端獲取JS可解析數據的方案,皆可稱Ajax.
最常見的另一種Ajax實現方案是JSONP,JS通過DOM接口,創建一個<script>節點,指定節點的src爲一個http地址到數據服務器,數據被包裝成可執行的JS,在http響應結束後立即執行.(這裏我們再一次涉及到了JS的執行入口之一,在瀏覽器遇到<script>節點是執行).

在MS,Google等先驅的引導之下,Ajax的出現引起了前端領域,乃至整個互聯網開發領域的深刻變革,即爲我們熟知的Web2.0.但回到本源,Ajax依然是瀏覽器中JavaScript能力的另一種擴展而已.

[b]總結一下[/b]
[list=1]
[*]HTTP:一切內容通過HTTP請求獲得
[*]HTML:瀏覽器把HTML解析成DOM樹
[*]CSS:定義HTML的佈局和樣式
[*]JavaScript:提供計算能力,處理交互事件
[*]Cookie:網頁間,請求間會話保持(JS可以操作Cookie)
[*]DHTML:JavaScript操作Dom樹(包括CSS)
[*]AJAX:JavaScript操縱HTTP
[/list][*]所有前端應用託生於這些基礎特性的整合
[*]Web2.0主要託生於DHTML和AJAX這類JavaScript的能力擴展

前端技術體系的介紹可以告一段落,我們並沒有把一個個概念的英文縮寫展開,然後抄來晦澀的官方的解釋.
"使用Http傳輸HTML文檔,文檔被解析成DOM樹,CSS負責佈局和樣式,JS提供計算能力,處理事件響應,Cookie維持會話."
沒錯,如果換你來寫一個瀏覽器,會不會也這樣做?那麼其他的客戶端圖形交互系統,是不是也一樣要完成傳輸,展現,事件交互等等功能?
如果我繼續介紹一下firebug這類前端開發工具,將其與七種武器對應上,再輔以一些API文檔,就可以嘗試體驗下前端開發了.

[b]最後和前端開發講幾句[/b]
讀到這裏的前端開發,先說聲抱歉,寫了這麼長,通篇都是你爛熟於心的內容.而且你明明瞭解更多,這裏卻沒有提到.
其實要點就在這裏,如何在你所有知道的內容中提出來若干要點,完整的描述前端技術體系,這件事情對於前端開發而言,重要麼?不重要麼?重要麼?不重要麼?我們看幾個問題:

爲什麼會有DHTML?
我們瞭解Http,HTML,CSS,JS的協作關係,知道DOM樹是一切的依託,我們纔會想到通過改變DOM樹來操縱網頁內的一切.

爲什麼會有Ajax?
我們瞭解DHTML的能力,卻不知道其用武之地,後來我們想到依靠服務端指導.接下來我們又知道所有服務端內容都是通過Http獲得,自然我們需要JavaScript能夠操作的Http對象.

這些問題需要前端開發去發現,去解決.雖然大家都在跟着先賢們的步子走,很少能成爲領域的開拓者,但是否瞭解整個前端技術體系的區別是你是否是在盲目跟風.區別是當一項新技術出現的時候是否能發現其解決的核心問題以及爲解決問題付出的額外代價.

引入新技術的需要付出的額外代價是我要強調的另一個重點,使用DHTML的代價是什麼,嚴重依賴Ajax的代價又是什麼?瞭解這些然後我們才能更好的權衡要不要使用.

前端的發展依然在繼續,遇到什麼問題?如何解決?
[*]Cookie容量小,每次隨Http發送,是否通過JS在客戶端存儲更多數據? -- LocalStorage
[*]JS單線程,能否讓JS進行大量計算的時候,頁面不再掛起? -- WebWorkers
[*]JS語言過於隨意,依賴繁雜,如何組織代碼能方便共享智慧? -- CommonJS Modules
[*]Http無狀態短連接,能否讓客戶端更及時收到服務端消息? -- 各種Comet
[*]Http頭較大無法壓縮,無法一個請求返回多個數據對象,怎麼辦? -- 使用SPDY協議

解決問題付出什麼代價?是否涵蓋了所有常用瀏覽器,如果不能是否做到了漸進增強?我們要不要這樣做?這些是做一名合格的前端,做一名對技術架構有影響力的前端,必然面對的問題.

前端技術體系,看起來題目很大,但其實並沒有玄之又玄的東西在裏邊,所以即便我寫的算不得優秀,但是說清楚還是可以的.我在面試高級前端的時候其實很在意前端大局觀,不然叫我如何放心的把一個將會持續發展的產品交到他手裏.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章