网络加速手段之一,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]

固然,并非合并为一个文件,下载的速度就必定快,具体的下载速度和策略还受到浏览器的影响,有的浏览器同时开的请求线程多,也会影响下载速度。可是整体来讲,若是文件数多的话,下载单一文件总会快点的。

相关文章
相关标签/搜索