zoukankan      html  css  js  c++  java
  • 网络加速手段之一,JS文件资源合并下载

    有过ftp下载文件经验的人都有体验,单独下载一个100M的文件比分开下载100个1M的文件速度快很多,这是因为下载需要解析域名,建立连接等额外开销的时间,因此下载100个文件就要做100次这种额外的开销。因此如果把这个100个文件整合成一个文件下载速度会快很多。

    基于上述的方法,可以对HTML中的JS文件也做类似的处理,无论js文件多少个,通过配置文件,把N个js文件合并到一个文件下载。实现手段通过httpHandler。具体代码如下:
    web.config文件中:
     
    <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中的值也会得到更新。
    Handler处理部分的代码如下:
     
    /// <summary>  
       /// GetJS 的摘要说明  
       /// </summary>  
       public class GetJS : IHttpHandler  
       {  
     
           public void ProcessRequest(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(" ", "").Replace(" ", "").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"] == "")  www.2cto.com
               {  
                   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]
    当然,并不是合并为一个文件,下载的速度就一定快,具体的下载速度和策略还受到浏览器的影响,有的浏览器同时开的请求线程多,也会影响下载速度。但是总体来说,如果文件数多的话,下载单一文件总会快点的。
     
    http://www.2cto.com/kf/201212/180484.html
  • 相关阅读:
    hihoCoder #1176 : 欧拉路·一 (简单)
    228 Summary Ranges 汇总区间
    227 Basic Calculator II 基本计算器II
    226 Invert Binary Tree 翻转二叉树
    225 Implement Stack using Queues 队列实现栈
    224 Basic Calculator 基本计算器
    223 Rectangle Area 矩形面积
    222 Count Complete Tree Nodes 完全二叉树的节点个数
    221 Maximal Square 最大正方形
    220 Contains Duplicate III 存在重复 III
  • 原文地址:https://www.cnblogs.com/chen110xi/p/4466219.html
Copyright © 2011-2022 走看看