網絡加速手段之一,JS文件資源合併下載

版權聲明: 本文由 一隻博客 發表於 bloghome博客javascript

文章連接: https://www.bloghome.com.cn/user/cnn237111java

有過ftp下載文件經驗的人都有體驗,單獨下載一個100M的文件比分開下載100個1M的文件速度快不少,這是由於下載須要解析域名,創建鏈接等額外開銷的時間,所以下載100個文件就要作100次這種額外的開銷。所以若是把這個100個文件整合成一個文件下載速度會快不少。jquery

基於上述的方法,能夠對HTML中的JS文件也作相似的處理,不管js文件多少個,經過配置文件,把N個js文件合併到一個文件下載。實現手段經過httpHandler。具體代碼以下:web

web.config文件中:json

<httpHandlers> 
      <add  verb="*" path="MergedJS.js" type="MergeJS.GetJS"/> 
</httpHandlers>

 

只對MergedJS.js的請求文件做合併,具體請求到哪一個文件,有querystring參數給定,好比本例中使用MergedJS.js?jsid=myjs這種方式。對於其餘類型的js文件,則按照IIS默認的請求方式處理。瀏覽器

  <appSettings>   
    <add key="myjs" value="jquery-1.4.1-vsdoc.js,   
jquery-ui-1.8.16.custom.min.js,   
jquery-1.4.1.js,   
jquery-1.7.min.js,   
jquery-1.5.2.min.js,   
jquery-1.4.1.min.js,   
jquery.maskedinput-1.3.js,   
json2.min.js,   
jquery.hotkeys-0.0.3.js,   
jquery.loadmask.min.js,   
My.js"/>   
  </appSettings>

 

上述配置,主要用來指定myjs使用哪些文件來合併。緩存

MergeJS.GetJS 這個HttpHandler主要用來處理js。此處涉及到一個緩存的問題,一般狀況下,js文件會默認緩存在本地瀏覽器緩存中,可是對於MergedJS.js這種經過httpHandler所處理的,被視爲動態內容,並不會緩存在瀏覽器中,而是每次都會從服務器端獲取最新的內容。所以能夠經過編碼,強制使用瀏覽器緩存。服務器

因爲反覆讀取js所作IO操做也是性能瓶頸,所以在global中首先將全部的js預讀存在dictionary中,用的時候直接從dictionary中輸出,避免了IO操做。代碼可以判斷js文件是否作了修改,若是修改了,dictionary中的值也會獲得更新。app

Handler處理部分的代碼以下:ide

/// <summary>  
   /// GetJS 的摘要說明  
   /// </summary>  
   public class GetJS : IHttpHandler  
   {  
 
       public void Proce***equest(HttpContext context)  
       {  
           context.Response.ContentType = "application/x-javascript";//表示是javascript文件類型  
           string jsid = context.Request.Params["jsid"].ToString();  
 
           //獲取全部須要Merge的文件  
           string[] jsfiles = System.Configuration.ConfigurationManager.AppSettings[jsid].ToString().Replace("\r", "").Replace("\n", "").Split(',');  
 
           //記錄文件的最後修改時間,取最新修改的那個文件的時間。  
           DateTime lastChangeTime = new DateTime();  
           StringBuilder sb = new StringBuilder();  
           foreach (var js in jsfiles)  
           {  
               if (Global.dic_jsfiles.ContainsKey(js))  
               {  
                   DateTime tmplastDateTime = new FileInfo(Global.dic_jsfiles[js].filefullName).LastWriteTime;  
 
                   tmplastDateTime = DateTime.Parse(tmplastDateTime.ToString("yyyy-MM-dd HH:mm:ss"));//去除毫秒信息。  
 
                   if (tmplastDateTime > Global.dic_jsfiles[js].lastModifiedTime)//若是最後修改時間更改,更新dic_jsfiles內容  
                   {  
                       Global.dic_jsfiles[js].content = Common.ReadFile(Global.dic_jsfiles[js].filefullName);//讀取新的文件  
                       Global.dic_jsfiles[js].lastModifiedTime = tmplastDateTime;  
                   }  
                     
               }  
               else//若是不存在,則讀取該文件  
               {   
                   string filename = context.Request.PhysicalApplicationPath + "Scripts\" + js.Trim();  
                   Global.dic_jsfiles.Add(filename,new jsFileInfo() {  
                       filefullName = filename,content=Common.ReadFile(filename),lastModifiedTime=new FileInfo(filename).LastWriteTime  
                     
                   });  
                   Common.ReadFile(Global.dic_jsfiles[js].filefullName);  
               }  
 
               sb.Append(Global.dic_jsfiles[js].content + ";");  
                
           }  
 
           //文件最後修改時間  
           lastChangeTime = Global.dic_jsfiles.Max(m => m.Value.lastModifiedTime);  
 
           DateTime If_Modified_Since = new DateTime();  
           if (context.Request.Headers["If-Modified-Since"] == null || context.Request.Headers["If-Modified-Since"] == "")  
           {  
               If_Modified_Since = new DateTime(1900, 1, 1);//若是讀取的請求頭中If-Modified-Since沒有值,就給它一個默認值爲19000101  
           }  
           else 
           {  
               If_Modified_Since = DateTime.Parse(context.Request.Headers["If-Modified-Since"]);  
           }  
           if (If_Modified_Since >= lastChangeTime)//若是客戶端請求頭中的時間最後一次修改時間,比真實的最後修改時間還新,則直接返回304代碼  
           {  
               context.Response.StatusCode = 304;//返回304代碼,使其讀取緩存  
               context.Response.End();  
           }  
           else//不然  
           {  
               //顯示內容  
               context.Response.AddHeader("last-modified", lastChangeTime.ToString());  
           }  
 
           context.Response.Write(sb.ToString());  
       }  
 
       private string ReadFile(string filename)  
       {  
           using (StreamReader sr = new StreamReader(filename, System.Text.UTF8Encoding.UTF8))  
           {  
               return sr.ReadToEnd();  
           }  
       }  
 
       public bool IsReusable  
       {  
           get 
           {  
               return false;  
           }  
       }  
   }

 

效果以下:使用組合下載的狀況,js的下載耗費時間73ms。

clipboard

可是分開下載的話就比較耗時。

clipboard[1]

固然,並非合併爲一個文件,下載的速度就必定快,具體的下載速度和策略還受到瀏覽器的影響,有的瀏覽器同時開的請求線程多,也會影響下載速度。可是整體來講,若是文件數多的話,下載單一文件總會快點的。

相關文章
相關標籤/搜索