有过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("\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"] == "")  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。
但是分开下载的话就比较耗时。
当然,并不是合并为一个文件,下载的速度就一定快,具体的下载速度和策略还受到浏览器的影响,有的浏览器同时开的请求线程多,也会影响下载速度。但是总体来说,如果文件数多的话,下载单一文件总会快点的。
 
http://www.2cto.com/kf/201212/180484.html

网络加速手段之一,JS文件资源合并下载的更多相关文章

  1. 利用Node 搭配uglify-js压缩js文件,批量下载图片到本地

    Node的便民技巧-- 压缩代码 下载图片 压缩代码 相信很多前端的同学都会在上线前压缩JS代码,现在的Gulp Webpack Grunt......都能轻松实现.但问题来了,这些都不会,难道就要面 ...

  2. js文件上传下载组件

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 先说下要求: PC端全平台支持,要求支持Windows,Mac,Linux 支持所 ...

  3. 兼容到ie10的js文件导出、下载到本地

    话不多说,上代码: try { let reader = new FileReader(); let blob = new Blob([res.data], { type: 'application/ ...

  4. js文件合并,压缩,缓存,延迟加载

    做web前段也有一段时间了,对于web中js文件的加载有些体会想跟大家一起分享一下. 1.首先说说js文件的合并和压缩吧 为了便于集中式管理js的合并和压缩我们创建一个Js.ashx文件来专门处理合并 ...

  5. 怎样把网站js文件合并成一个?几种方法可以实现

    我们在建网站时经常会用js特效代码以使页面更美观,比如js幻灯片代码.js下拉菜单等,但是网页特效一多,如果js文件没有合并的话会降低网站的性能,这时我们就要考虑合并js文件了,ytkah总结了以下几 ...

  6. 压缩/批量压缩/合并js文件

    写在前面 如果文件少的话,直接去网站转化一下就行. http://tool.oschina.net/jscompress?type=3 1.压缩单个js文件 cnpm install uglify-j ...

  7. 页面js脚本与img等资源的下载顺序问题。

    引言问题 <img src="background.jpg"><script src="test.js"></script> ...

  8. Tengine的concat模块与js、css合并

    首先,先走出一个误区 ,下面是tengine-cn邮件列表里的一篇邮件原文:“看了这个例子就了解了,这个所谓的合并请求只是把所有的CSS或JAVASCRIPT请求合并,必须是同一个文件类型的.我开始想 ...

  9. JS&CSS文件请求合并及压缩处理研究(一)

    在我们日常的网站开发工作中,一个页面难免会引用到各种样式及脚本文件.了解Web开发的朋友们都知道,页面引用的每一个: <link href="style.css" rel=& ...

随机推荐

  1. JavaWeb笔记——JSTL标签

    JSTL 1. jstl的概述   * apache的东西,依赖EL   * 使用jstl需要导入jstl.jar.standard.jar   * 四大库:     > core:核心库,重点 ...

  2. WordPress主题制作教程2:导航菜单制作

    实现自定义菜单,需要用到的函数是wp_nav_menu(); 在主题目录下的functions.php的 <?php ….. ?> 之间,添加以下菜单注册代码,这样你就可以在主题文件中使用 ...

  3. char[] 操作

    字符串的初始化方法1.char str[10] = { 'H', 'e', 'l', 'l', 'o', '\0' };2.char str[10] = "Hello";   ch ...

  4. Linux命令-cp

    cp命令用于复制文件到目录 参数 -r 递归持续复制(用于目录) 参数 -p 保留原始文件属性 参数 -d 若对象为链接文件,保留该链接文件的属性 参数 -a 相当于以上三者之和(-pdr) [roo ...

  5. SSIS ->> Script Task

    利用Script Task,我们可以做一些本身SSIS没能满足我们的,或者实现起来效果不够理想的.比如说我们想做一件这样的事情,去检查某个文件是否为空.如果我们通过Row Count组件来实现,性能上 ...

  6. Maven实战(六)--- dependencies与dependencyManagement的区别

    在上一个项目中遇到一些jar包冲突的问题,之后还有很多人分不清楚dependencies与dependencyManagement的区别,本篇文章将这些区别总结下来. 1.DepencyManagem ...

  7. JVM的相关知识整理和学习--(转载)

    JVM是虚拟机,也是一种规范,他遵循着冯·诺依曼体系结构的设计原理.冯·诺依曼体系结构中,指出计算机处理的数据和指令都是二进制数,采用存储程序方式不加区分的存储在同一个存储器里,并且顺序执行,指令由操 ...

  8. MDM平台学习笔记

    最近和将来一段时间都会花很多时间在主数据管理平台的学习和开发上,从现在开始打算记录此过程中的知识点和学习心得,加油! 1.IBM全新的产品文档网站IBM Knowledge Center,软件硬件产品 ...

  9. mysql安装图解 mysql图文安装教程(详细说明)

    MySQL5.0版本的安装图解教程是给新手学习的,当前mysql5.0.96是最新的稳定版本. mysql 下载地址 http://www.jb51.net/softs/2193.html 下面的是M ...

  10. CAS 在 Tomcat 中实现单点登录

    单点登录(Single Sign On , 简称 SSO )是目前比较流行的服务于企业业务整合的解决方案之一, SSO 使得在多个应用系统 中,用户只需要登录一次就可以访问所有相互信任的应用系统.CA ...