介紹
使用許多小得JS、CSS文件代替一個(gè)龐大的JS或CSS文件來讓代碼獲得更好的可維 護(hù)性,這是一個(gè)很好的實(shí)踐。但這樣做反過來卻損失了網(wǎng)站的性能。雖然你應(yīng)該將你的javascript代碼寫在小文件中并且將大的CSS文件分割到小文件 中,當(dāng)一個(gè)瀏覽器請(qǐng)求那些JS以及CSS文件,它卻將為每一個(gè)文件產(chǎn)生一個(gè)請(qǐng)求。每一個(gè)HTTP請(qǐng)求將導(dǎo)致從你的瀏覽器到服務(wù)器上的一次"往返",從響應(yīng) 服務(wù)器到客戶端瀏覽器之間的等待時(shí)間稱之為"延時(shí)"。因此,如果你有四個(gè)JS文件以及三個(gè)CSS文件需要被頁面加載,你將要等待七次網(wǎng)絡(luò)上的"往返"。在 本國(guó)內(nèi),延時(shí)平均為70ms。所以總延時(shí)為490ms,大概半秒鐘。而來自國(guó)外的訪問,平均延時(shí)大概在200ms左右。因此,那意味著1400ms的時(shí)間 浪費(fèi)。而直到CSS與JS文件被完全加載,頁面才會(huì)被完全地顯示出來。所以,越長(zhǎng)時(shí)間的延時(shí),頁面加載地越慢。
延時(shí)有多糟糕
這里有一張圖片顯示了,每一個(gè)請(qǐng)求怎樣產(chǎn)生了"延時(shí)",這些"延時(shí)"累加起來顯著地影響了頁面的加載:
你可以通過使用CDN(Content Delivery Network)來減少等待時(shí)間。然而,一個(gè)更好的解決方案是使用HttpHandler提供多個(gè)文件的一次請(qǐng)求,該HttpHandler整合了數(shù)個(gè)文 件并且提供了一次輸出。所以,代之以許多的<scropt>或者<link>標(biāo)簽,你只需要寫一個(gè)<scropt> 以及<link>標(biāo)簽,并將它們標(biāo)記在HttpHandler中。由你來告訴handler哪些文件需要被整合,并且它提供了哪些文件的一次 輸出。這省去了從瀏覽器發(fā)出許多請(qǐng)求產(chǎn)生的延時(shí)。
這里你能看到如果你把多個(gè)JS文件以及CSS文件整合到一個(gè)輸出里,有怎樣的性能提升。
在通常的網(wǎng)頁中,你將看到很多的JS引用:
而我們可以僅用一個(gè)<script>標(biāo)簽請(qǐng)求整個(gè)JS文件的集合,來代替這里的每一個(gè)<script>標(biāo)簽:
HttpHandler讀取定義在一個(gè)配置文件中的文件名,整合所有的那些文件,并將 它們一次響應(yīng)到客戶端。它通過gzip來壓縮響應(yīng)內(nèi)容以此節(jié)約帶寬。另外它提供一個(gè)帶有cache的響應(yīng)請(qǐng)求頭來緩存響應(yīng)到瀏覽器的Cache里,使得瀏 覽器對(duì)之后的訪問不需要再次請(qǐng)求它。
在請(qǐng)求參數(shù)中,你可以用"S"參數(shù)標(biāo)識(shí)文件集合的名稱,然后用"t"參數(shù)來標(biāo)識(shí)content type,然后使用"v"參數(shù)來標(biāo)識(shí)一個(gè)版本。因?yàn)轫憫?yīng)被緩存了,如果你修改了文件集合中的任何一個(gè),你將不得不增加參數(shù)"v"的值來讓瀏覽器再次下載響應(yīng)。
使用該HttpHandler,你可以這樣來請(qǐng)求CSS文件:
這里列出了你將需要怎樣來定義請(qǐng)求的集合,在web.config中:
使用HttpHandler整合器的例子
我構(gòu)建了一個(gè)簡(jiǎn)單的測(cè)試網(wǎng)站來向你展示它的使用,該測(cè)試網(wǎng)站有兩個(gè)CSS以及JS文件。Default.aspx僅使用一個(gè)<link>和<script>標(biāo)簽通過HttpCombiner.ashx來請(qǐng)求它們。
下面是Default.aspx文件的內(nèi)容:
就像你看到的那樣,有一個(gè)<link>標(biāo)簽向HttpCombiner.ashx發(fā)送了一個(gè)請(qǐng)求并提供了請(qǐng)求集合的名稱——Set_Css,當(dāng)然還有一個(gè)<script>標(biāo)簽請(qǐng)求了一個(gè)Set_Javascript的集合。
上面的兩個(gè)集合都被定義在web.config文件中:
這里列出了Handler如何工作:
(1)????首先,它會(huì)從"s"參數(shù)中讀取文件集合的名稱
(2)????然后它從web.config文件中拿到集合的定義
(3)????它讀取每一個(gè)文件,然后將它們緩存在緩沖區(qū)中
(4)????緩沖區(qū)然后通過gzip進(jìn)行壓縮
(5)????被壓縮后的緩沖區(qū)內(nèi)的內(nèi)容將被發(fā)送到瀏覽器
(6)????被壓縮后的緩沖區(qū)內(nèi)的內(nèi)容被存儲(chǔ)在ASP.NET緩沖中,以讓隨后的對(duì)相同集合的請(qǐng)求能夠直接地從Cache中獲取數(shù)據(jù),而不是從文件系統(tǒng)或外部的URL去讀取每一個(gè)文件。
Handler帶來的好處:
(1)????它減少了網(wǎng)絡(luò)上的"往返"次數(shù),你把越多的文件放到一個(gè)集合中,就越能減少網(wǎng)絡(luò)延時(shí),它提高了性能。
(2)????它緩存了所有的整合過的壓縮響應(yīng),因此省去了一次又一次的讀取文件系統(tǒng)并壓縮它。它提供了可擴(kuò)展性。
HttpHandler如何工作
首先handler從請(qǐng)求字符串中讀取集合名、類型以及版本:
如果要加載的文件集合已經(jīng)被緩存了,那將直接從cache中寫入響應(yīng)流。否則,文件將被一個(gè)接一個(gè)地加載,然后被存儲(chǔ)在一個(gè)MemoryStream。MemoryStream被通過GzipStream壓縮(如果瀏覽器支持壓縮輸出)。
在整合了所有的文件并壓縮后,被整合的字節(jié)流被緩存起來,以讓隨后的請(qǐng)求可以直接地從緩存獲取數(shù)據(jù)。
GetFileBytes方法讀取一個(gè)文件或者URL,然后返回字節(jié)。所以,你可以在你的網(wǎng)站里使用虛擬路徑,或者你可以使用URL指向一個(gè)宿主在另外的域中的Js/Css文件。
WriteBytes方法有許多技巧在里面。它提供了一個(gè)基于是否字節(jié)是壓縮格式的響應(yīng)頭。然后它提供了一個(gè)緩存標(biāo)識(shí)頭,讓瀏覽器緩存響應(yīng)內(nèi)容。
怎樣使用這個(gè)handler呢?
原文鏈接:http://www.codePRoject.com/KB/aspnet/HttpCombine.aspx
? ?源代碼: http://download.csdn.net/detail/yanghua_kobe/3654006
譯者注: 今天在嘗試使用該技術(shù)時(shí),遇到一個(gè)問題。那就是在打包壓縮CSS文件時(shí)。如果文件中涉及到圖片路徑(例如background-img的url屬性時(shí))。 無法正確請(qǐng)求圖片。原因是,通常這些圖片都使用的是相對(duì)路徑。瀏覽器通常情況下載獲取到CSS文件后,會(huì)以CSS文件本身作為參考,根據(jù)圖片的相對(duì)路徑來 查找圖片。而批量打包時(shí),用來參考的路徑本身變成了handler的路徑,因而會(huì)導(dǎo)致查找圖片的路徑出錯(cuò)而無法下載。其實(shí)就算是人為將圖片的路徑設(shè)置成相 對(duì)于本handler的相對(duì)路徑仍然無法下載!
解決方案: 采用絕對(duì)路徑,但也取決于網(wǎng)站的發(fā)布方式。如果發(fā)布時(shí)新建的網(wǎng)站,那么可以直接通過"/"來從根目錄開始表達(dá)CSS中的背景圖片的絕對(duì)路徑。因?yàn)樾陆ňW(wǎng)站 時(shí),可以直接用"/"來標(biāo)識(shí)根目錄。而新建虛擬目錄時(shí),則需要加入新建虛擬目錄的文件夾名。如myweb,則絕對(duì)路徑表示為"/myweb /images......."這樣才能正確地獲取圖片。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注