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