在服务端合并css和js以减少http请求数
Web性能优化最佳实践中最重要的一条是减少HTTP请求,它也是YSlow中比重最大的一条规则。减少HTTP请求的方案主要有合并JavaScript和CSS文件、CSS Sprites、图像映射(Image Map)和使用Data URI来编码图片。
这段代码实现js和css服务端合并输出, 需要注意的是一定要在web服务器上为merge.aspx设定输出缓存.
[代码] 调用示例
<link href="/merge/?e=utf-8&file=/css/common.css:/css/base.css:/css/pagination.css" rel="stylesheet" type="text/css" /> <script src="/merge/?e=utf-8&file=/js/jquery.min.js:/js/jquery.pagination.js:/js/jquery.ns_bub.js:/js/common.js:/js/search_suggest.js" type="text/javascript"></script> <!-- merge.aspx设置缓存之后, 该文件的内容可能是长期不变的, 因此当所请求的资源发生改动时, 仍然会收到304. 所以若缓存时间较长影响实时性的话要更变url参数或自行实现缓存机制 --> <link href="/merge/?a=common.css改了请重新下载不然只好7天后才看到效果&e=utf-8&file=/css/common.css:/css/base.css:/css/pagination.css" rel="stylesheet" type="text/css" />
[代码] merge.aspx
<%@ Page Language="C#" AutoEventWireup="true" Inherits="System.Web.UI.Page" %> <%@ Import Namespace="System.Globalization" %> <%@ Import Namespace="System.Net" %> <script runat="server"> protected void Page_Load(object sender, EventArgs e) { if (string.IsNullOrEmpty(Request.QueryString["file"]) || string.IsNullOrEmpty(Request.QueryString["e"])) return; //以冒号分隔的url列表 var files = Server.UrlDecode(Request.QueryString["file"]).Split(':'); //url的过滤 var uris = files.Select(x => new Uri(Request.Url, x))//基于本页面构建待请求的uri .Where(x => //不允许请求外部资源 x.Authority == Request.Url.Authority //只能请求.css,js两种资源 && x.AbsolutePath.EndsWith(".css", true, CultureInfo.InvariantCulture) || x.AbsolutePath.EndsWith(".js", true, CultureInfo.InvariantCulture) ); if (!uris.Any()) return; //考虑安全性和资源文件可能是非静态的, 因此用http请求而不是直接file读取 var wc = new WebClient { Encoding = Encoding.GetEncoding(Request.QueryString["e"]) }; var content_type = new[] { "text/css", "application/x-javascript" }; //设置content-type为css或js Response.ContentType = uris.First().AbsolutePath.EndsWith(".css") ? content_type[0] : content_type[1]; //输出 Response.Write( uris.Select(wc.DownloadString).Aggregate((x1, x2) => //在每个js结尾补";"防止未结束的语句导致异常 x1 + (Response.ContentType == content_type[1] ? ";" : "") + Environment.NewLine + x2) ); } </script>