用HttpCombiner来减少js和css的请问次数
- HttpCombiner也不记得是谁写的了,功能是把多个js文件或css文件合并到一块,压缩一下一起发给客户端来优化网站。
- 用法是这样的:
- <script type="text/javascript" src="/Part/Handle/HttpCombiner.ashx?t=js&s=a.js,b.js,dialog/c.js,dialog/d.js"></script>
- 但这样又不利于找错,所以在中间又加了一个方法,可随时控制是如上引用还是,如下一般引用:
- <script type="text/javascript" src="/RES/JS/a.js"></script>
- <script type="text/javascript" src="/RES/JS/b.js"></script>
- <script type="text/javascript" src="/RES/JS/dialog/c.js"></script>
- <script type="text/javascript" src="/RES/JS/dialog/d.js"></script>
- 修改后引用文件时:
- <%= HttpCombiner.Requires(true,"js","a.js", "b.js", "dialog/c.js", "dialog/d.js")%>
- 第一个参数来控制合并 。
- 一般处理程序cs源码:
- 复制代码
- using System;
- using System.Web;
- using System.Net;
- using System.IO;
- using System.IO.Compression;
- using System.Text;
- using System.Web.Caching;
- public class HttpCombiner : IHttpHandler
- {
- #region Config
- private const bool DO_GZIP = true;
- private readonly static TimeSpan CACHE_DURATION = TimeSpan.FromDays();
- private const string JSPathPre = "~/RES/JS/";
- private const string CSSPathPre = "~/RES/CSS/";
- private const string CombinerUrl = "/Part/Handle/HttpCombiner.ashx";//些handler路径
- private const string JSAbsPathPre = "/RES/JS/";
- private const string CSSAbsPathPre = "/RES/CSS/";
- #endregion
- #region Requires 默认combin
- public static string Requires(bool combin, string type, params string[] files)
- {
- if (combin)
- {
- if (type == "js")
- {
- return string.Format("<script type=\"text/javascript\" src=\"{0}?t=js&s={1}\"></script>", CombinerUrl, string.Join(",", files));
- }
- else if (type == "css")
- {
- return string.Format("<link rel=\"stylesheet\" type=\"text/css\" href=\"{0}?t=css&s={1}\" />", CombinerUrl, string.Join(",", files));
- }
- else
- {
- return string.Empty;
- }
- }
- else
- {
- if (type == "js")
- {
- StringBuilder sb = new StringBuilder();
- foreach (var file in files)
- {
- sb.AppendFormat("<script type=\"text/javascript\" src=\"{0}{1}\"></script>", JSAbsPathPre, file);
- sb.AppendLine();
- }
- return sb.ToString();
- }
- else if (type == "css")
- {
- StringBuilder sb = new StringBuilder();
- foreach (var file in files)
- {
- sb.AppendFormat("<link rel=\"stylesheet\" type=\"text/css\" href=\"{0}{1}\" />", CSSAbsPathPre, file);
- sb.AppendLine();
- }
- return sb.ToString();
- }
- else
- {
- return string.Empty;
- }
- }
- }
- public static string Requires(string type, params string[] files)
- {
- return Requires(true, type, files);
- }
- #endregion
- #region Process
- public void ProcessRequest(HttpContext context)
- {
- HttpRequest request = context.Request;
- string setName = request["s"] ?? string.Empty;
- string contentType = request["t"] ?? string.Empty;
- if (string.IsNullOrEmpty(contentType))
- {
- contentType = "type/javascript";
- }
- else
- {
- if (contentType == "js")
- {
- contentType = "type/javascript";
- }
- else if (contentType == "css")
- {
- contentType = "text/css";
- }
- else
- {
- contentType = "text/plain";
- }
- }
- bool isCompressed = DO_GZIP && CanGZip(context.Request);
- UTF8Encoding encoding = new UTF8Encoding(false);
- if (!WriteFromCache(context, setName, isCompressed, contentType))
- {
- System.Collections.Generic.List<string> dependencyFiles = new System.Collections.Generic.List<string>();
- using (MemoryStream memoryStream = new MemoryStream())
- {
- using (Stream writer = isCompressed ?
- (Stream)(new GZipStream(memoryStream, CompressionMode.Compress)) :
- memoryStream)
- {
- string[] fileNames = setName.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
- foreach (string fileName in fileNames)
- {
- byte[] fileBytes = GetFileBytes(contentType, context, fileName.Trim(), encoding, dependencyFiles);
- writer.Write(fileBytes, , fileBytes.Length);
- }
- writer.Close();
- }
- byte[] responseBytes = memoryStream.ToArray();
- context.Cache.Insert(GetCacheKey(setName, isCompressed), responseBytes, new CacheDependency(dependencyFiles.ToArray()), System.Web.Caching.Cache.NoAbsoluteExpiration, CACHE_DURATION);
- WriteBytes(responseBytes, context, isCompressed, contentType);
- }
- }
- }
- private static byte[] GetFileBytes(string contentType, HttpContext context, string virtualPath, Encoding encoding, System.Collections.Generic.List<string> depencesFile)
- {
- if (virtualPath.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase))
- {
- using (WebClient client = new WebClient())
- {
- return client.DownloadData(virtualPath);
- }
- }
- else
- {
- if (!virtualPath.StartsWith("~/", StringComparison.InvariantCultureIgnoreCase))
- {
- if (contentType == "text/css")
- {
- virtualPath = CSSPathPre + virtualPath;
- }
- else if (contentType == "type/javascript")
- {
- virtualPath = JSPathPre + virtualPath;
- }
- }
- string physicalPath = context.Server.MapPath(virtualPath);
- depencesFile.Add(physicalPath);
- byte[] bytes = File.ReadAllBytes(physicalPath);
- return bytes;
- }
- }
- private static bool WriteFromCache(HttpContext context, string setName,bool isCompressed, string contentType)
- {
- byte[] responseBytes = context.Cache[GetCacheKey(setName, isCompressed)] as byte[];
- if (null == responseBytes || == responseBytes.Length) return false;
- WriteBytes(responseBytes, context, isCompressed, contentType);
- return true;
- }
- private static void WriteBytes(byte[] bytes, HttpContext context,bool isCompressed, string contentType)
- {
- HttpResponse response = context.Response;
- response.AppendHeader("Content-Length", bytes.Length.ToString());
- response.ContentType = contentType;
- if (isCompressed) response.AppendHeader("Content-Encoding", "gzip");
- context.Response.Cache.SetCacheability(HttpCacheability.Public);
- context.Response.Cache.SetExpires(DateTime.Now.Add(CACHE_DURATION));
- context.Response.Cache.SetMaxAge(CACHE_DURATION);
- context.Response.Cache.AppendCacheExtension("must-revalidate, proxy-revalidate");
- response.OutputStream.Write(bytes, , bytes.Length);
- response.Flush();
- }
- private static bool CanGZip(HttpRequest request)
- {
- string acceptEncoding = request.Headers["Accept-Encoding"];
- if (!string.IsNullOrEmpty(acceptEncoding) && (acceptEncoding.Contains("gzip") || acceptEncoding.Contains("deflate")))
- return true;
- return false;
- }
- private static string GetCacheKey(string setName, bool isCompressed)
- {
- return "HttpCombiner." + setName + "." + isCompressed;
- }
- public bool IsReusable
- {
- get
- {
- return true;
- }
- }
- #endregion
- 复制代码
- }
用HttpCombiner来减少js和css的请问次数的更多相关文章
- Web性能优化-合并js与css,减少请求
Web性能优化已经是老生常谈的话题了, 不过笔者也一直没放在心上,主要的原因还是项目的用户量以及页面中的js,css文件就那几个,感觉没什么优化的.人总要进步的嘛,最近在被angularjs吸引着,也 ...
- IE和firefox火狐在JS、css兼容区别
1.firefox不能对innerText支持. firefox支持innerHTML但却不支持innerText,它支持textContent来实现innerText,不过默认把多余的空格也保留了. ...
- [转][前端优化]使用Combres合并对js、css文件的请求
本文转自:http://www.cnblogs.com/parry/archive/2011/01/28/Reduce_Http_Request_Using_Combres_For_Js_Css.ht ...
- 将Microsoft Ajax Minifier集成到VS2013对JS、CSS进行编译时压缩
在网站发布中,一般要将js,css文件压缩减少体积,以减少在HTTP请求中的流量.将Microsoft Ajax Minifier集成到VS2013中就可以对JS.CSS进行编译时压缩. VS2013 ...
- MVC中的JS和CSS压缩
小说一下Js和CSS压缩的好处: 1.减小了文件的体积 2.减小了网络传输量和带宽占用 3.减小了服务器的处理的压力 4.提高了页面的渲染显示的速度 很多建议将站点的静态文件(如图片.js.css ...
- 为js和css文件自动添加版本号
web应用必然要面对缓存问题,无论前台后台都会涉足缓存.特别是对于前端而言,缓存利用的是否得当直接关系到应用的性能. 通常情况下,我们会倾向于使用缓存,因为缓存一方面可以减少网络开销,一方面可以减轻服 ...
- nginx js、css多个请求合并为一个请求(concat模块)
模块介绍 mod_concat模块由淘宝开发,目前已经包含在tengine中,并且淘宝已经在使用这个nginx模块.不过塔暂时没有包含在nginx中.这个模块类似于apache中的modconcat. ...
- PHP中,JS和CSS优化工具Minify的使用方法
为减少HTTP请求,我们往往需要合并和压缩多个JS和CSS文件,下面记录下网上关于实现这个功能的PHP源码以及开源项目Minify的使用方法 一.实现合并和压缩多个JS和CSS文件的代码请参考 1.一 ...
- 经验总结:按需加载JS和css
项目中做过这样的事情:所有页面都通过SSI指令 include这样一份public-js.shtml, 用来引入涉及到的js(包括公共的脚本 验证插件 自定义组件等),但是一些没有交互效果的页面根本不 ...
随机推荐
- Java中的overload(方法的覆写)
方法覆写(overload)与方法的重载非常相似,它在 Java的继承中也有很重要的应用. 写程序可能会碰到下面的情况,在父类中已经实现的方法可能不够精确,不能满足子类 的需求.例如在前面的 Anim ...
- 新人浅谈__(数据库的设计__数据库模型图,数据库E-R图,三大范式)
>>>> 为什么需要规范的数据库设计 在实际的项目开发中,如果系统的数据存储量较大,设计的表比较多,表和表之间的关系比较复杂,就需要首先考虑规范的数据库设计,然后进行创建库, ...
- 使用Kettle增量抽取MongoDB数据实践
需求: 增量抽取MongoDB数据并加载到MSSQL 由于不能使用关系型数据库的自定义SQL, 所以主要遇到的问题有: 增量时间的查询和参数控制 ETL的批次信息和调用参数的写入 第一个问题的解决如下 ...
- 移动web——bootstrap媒体对象
基本模板 1.这些组件都具有在文本内容的左或右侧对齐的图片(就像博客评论或 Twitter 消息等) <div class="media"> <div class ...
- JS——事件冒泡与捕获
事件冒泡与事件捕获 1.冒泡:addEventListener("click",fn,false)或者addEventListener("click",fn): ...
- JAVA趣味逻辑算法
/**已知4位同学中的一位数学考了100分,当小李询问这4位是谁考了100分时,4个人的回答如下: A说:不是我. B说:是C C说:是D. D说:他胡说. 已知三个人说的是真话,一个人说的是假话.现 ...
- select2下拉插件
下拉单选: 1.行内 1)初始化数据: <select class="form-control select5"> <option selected>张三1 ...
- python socket 接口
一.简介 socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求.socket起 ...
- js的三种对象
JS中,可以将对象分为“内部对象”.“宿主对象”和“自定义对象”三种. 1,内部对象 js中的内部对象包括Array.Boolean.Date.Function.Global.Math.Number. ...
- Java中“==”、“compareTo()”和“equals()”的区别
在比较两个对象或者数据大小的时候,经常会用到==.compareTo()和equals(),尤其是在接入了Comparable接口后重写compareTo方法等场景,所以我们来理一下这三个的区别. 1 ...