尝试这个:
我最近完成了相当多的研究工作,并随后进行了一些开发工作,这些工作对提高Web应用程序前端的性能大有帮助。我以为我会在这里分享基本的解决方案。
首先要做的是使用Yahoo的YSlow和Google的PageSpeed对您的网站进行基准测试。这些将凸显出“垂头丧气”的性能改进。除非您已经这样做,否则最终的建议几乎肯定会包括组合,缩小和gzip您的静态内容。
我们将要执行的步骤是:
编写一个自定义HTTPHandler来组合和缩小CSS。编写一个自定义HTTPHandler来组合和缩小JS。包括一种机制,以确保上述内容仅在应用程序不处于调试模式时才能发挥作用。编写自定义服务器端Web控件以轻松维护css / js文件的包含。在IIS 6上启用某些内容类型的GZIP。首先,让我们从实现.NET IHttpHandler接口的CSSHandler.asax开始:
using System;using System.Collections.Generic;using System.IO;using System.Text;using System.Web;namespace WebApplication1{ public class CssHandler : IHttpHandler { public bool IsReusable { get { return true; } } public void ProcessRequest(HttpContext context) { string[] cssFiles = context.Request.QueryString["cssfiles"].Split(','); List<string> files = new List<string>(); StringBuilder response = new StringBuilder(); foreach (string cssFile in cssFiles) { if (!cssFile.EndsWith(".css", StringComparison.OrdinalIgnoreCase)) { //log custom exception context.Response.StatusCode = 403; return; } try { string filePath = context.Server.MapPath(cssFile); string css = File.ReadAllText(filePath); string compressedCss = Yahoo.Yui.Compressor.CssCompressor.Compress(css); response.Append(compressedCss); } catch (Exception ex) { //log exception context.Response.StatusCode = 500; return; } } context.Response.Write(response.ToString()); string version = "1.0"; //your dynamic version number context.Response.ContentType = "text/css"; context.Response.AddFileDependencies(files.ToArray()); HttpCachePolicy cache = context.Response.Cache; cache.SetCacheability(HttpCacheability.Public); cache.VaryByParams["cssfiles"] = true; cache.SetETag(version); cache.SetLastModifiedFromFileDependencies(); cache.SetMaxAge(TimeSpan.FromDays(14)); cache.SetRevalidation(HttpCacheRevalidation.AllCaches); } }}好的,现在一些解释:
IsReUsable属性:
我们没有处理任何特定于实例的事情,这意味着我们可以安全地重用处理程序的同一实例来处理多个请求,因为我们的ProcessRequest是线程安全的。更多信息。
ProcessRequest方法:
这里没有什么太忙的事情。我们正在遍历提供给我们的CSS文件(请参阅下面的CSSControl,了解它们的输入方式),并使用Yahoo的YUICompressor的.NET端口压缩每个文件,然后再将内容添加到输出响应流中。
该方法的其余部分涉及设置一些HTTP缓存属性,以进一步优化浏览器客户端下载(或视情况而定)下载内容的方式。
我们在代码中设置了Etags,以便它们在服务器场中的所有计算机上都相同。我们在实际文件上设置了响应和缓存依赖关系,因此,如果替换它们,缓存将失效。我们设置可缓存性,以便代理可以缓存。我们使用cssfiles属性来VaryByParams,以便我们可以缓存通过处理程序提交的每个CSS文件组。这是CSSControl,它是继承.NET LiteralControl的自定义服务器端控件。
面前:
<customcontrols:csscontrol id="cssControl" runat="server"> <CustomControls:Stylesheet File="main.css" /> <CustomControls:Stylesheet File="layout.css" /> <CustomControls:Stylesheet File="formatting.css" /></customcontrols:csscontrol>
背部:
using System;using System.Collections.Generic;using System.ComponentModel;using System.Web;using System.Web.UI;using System.Linq;using TTC.iTropics.Utilities;namespace WebApplication1{ [DefaultProperty("Stylesheets")] [ParseChildren(true, "Stylesheets")] public class CssControl : LiteralControl { [PersistenceMode(PersistenceMode.InnerDefaultProperty)] public List<Stylesheet> Stylesheets { get; set; } public CssControl() { Stylesheets = new List<Stylesheet>(); } protected override void Render(HtmlTextWriter output) { if (HttpContext.Current.IsDebuggingEnabled) { const string format = "<link rel="Stylesheet" href="stylesheets/{0}"></link>"; foreach (Stylesheet sheet in Stylesheets) output.Write(format, sheet.File); } else { const string format = "<link type="text/css" rel="Stylesheet" href="stylesheets/CssHandler.ashx?cssfiles={0}&version={1}"/>"; IEnumerable<string> stylesheetsArray = Stylesheets.Select(s => s.File); string stylesheets = String.Join(",", stylesheetsArray.ToArray()); string version = "1.00" //your version number output.Write(format, stylesheets, version); } } } public class Stylesheet { public string File { get; set; } }}HttpContext.Current.IsDebuggingEnabled已连接到web.config中的以下设置:
<system.web> <compilation debug="false"></system.web>
因此,基本上,如果您的站点处于调试模式,则将获得如下所示的HTML标记:
<link rel="Stylesheet" href="stylesheets/formatting.css"></link><link rel="Stylesheet" href="stylesheets/layout.css"></link<link rel="Stylesheet" href="stylesheets/main.css"></link>
但是,如果您处于生产模式(debug = false),则将获得如下标记:
<link type="text/css" rel="Stylesheet" href="CssHandler.ashx?cssfiles=main.css,layout.css,formatting.css&version=1.0"/>
然后,后者显然将调用CSSHandler,它将负责组合,最小化和缓存读取静态CSS内容。
然后,您还可以为静态Javascript内容复制以上所有内容:
`JSHandler.ashx:
using System;using System.Collections.Generic;using System.IO;using System.Text;using System.Web;namespace WebApplication1{ public class JSHandler : IHttpHandler { public bool IsReusable { get { return true; } } public void ProcessRequest(HttpContext context) { string[] jsFiles = context.Request.QueryString["jsfiles"].Split(','); List<string> files = new List<string>(); StringBuilder response = new StringBuilder(); foreach (string jsFile in jsFiles) { if (!jsFile.EndsWith(".js", StringComparison.OrdinalIgnoreCase)) { //log custom exception context.Response.StatusCode = 403; return; } try { string filePath = context.Server.MapPath(jsFile); files.Add(filePath); string js = File.ReadAllText(filePath); string compressedJS = Yahoo.Yui.Compressor.JavascriptCompressor.Compress(js); response.Append(compressedJS); } catch (Exception ex) { //log exception context.Response.StatusCode = 500; return; } } context.Response.Write(response.ToString()); string version = "1.0"; //your dynamic version number here context.Response.ContentType = "application/javascript"; context.Response.AddFileDependencies(files.ToArray()); HttpCachePolicy cache = context.Response.Cache; cache.SetCacheability(HttpCacheability.Public); cache.VaryByParams["jsfiles"] = true; cache.VaryByParams["version"] = true; cache.SetETag(version); cache.SetLastModifiedFromFileDependencies(); cache.SetMaxAge(TimeSpan.FromDays(14)); cache.SetRevalidation(HttpCacheRevalidation.AllCaches); } }}及其随附的JSControl:
面前:
<customcontrols:JSControl ID="jsControl" runat="server"> <customcontrols:script File="jquery/jquery-1.3.2.js" /> <customcontrols:script File="main.js" /> <customcontrols:script File="creditcardpayments.js" /></customcontrols:JSControl>
背部:
using System;using System.Collections.Generic;using System.ComponentModel;using System.Web;using System.Web.UI;using System.Linq;namespace WebApplication1{ [DefaultProperty("scripts")] [ParseChildren(true, "scripts")] public class JSControl : LiteralControl { [PersistenceMode(PersistenceMode.InnerDefaultProperty)] public List<script> scripts { get; set; } public JSControl() { scripts = new List<script>(); } protected override void Render(HtmlTextWriter writer) { if (HttpContext.Current.IsDebuggingEnabled) { const string format = "<script src="scripts\{0}"></script>"; foreach (script script in scripts) writer.Write(format, script.File); } else { IEnumerable<string> scriptsArray = scripts.Select(s => s.File); string scripts = String.Join(",", scriptsArray.ToArray()); string version = "1.0" //your dynamic version number const string format = "<script src="https://www.mshxw.com/skin/sinaskin/image/nopic.gif"></script>"; writer.Write(format, scripts, version); } } } public class script { public string File { get; set; } }}启用GZIP:
正如Jeff Atwood所说,在您的网站服务器上启用Gzip是一件容易的事。经过一些跟踪,我决定在以下文件类型上启用Gzip:
.css .js .axd(Microsoft Javascript文件).aspx(常规ASP.NET Web窗体内容).ashx(我们的处理程序)要在IIS 6.0 Web服务器上启用HTTP压缩,请执行以下操作:
打开IIS,右键单击“网站”,“服务”选项卡,启用“压缩应用程序文件”和“压缩静态文件”。停止IIS在记事本中打开IIS元数据库(C: WINDOWS system32 inetsrv metabase.xml)–如果需要,请进行备份。担心这些事情,找到并覆盖以下两个IIsCompressionScheme和一个IIsCompressionSchemes元素:
就是这样!这节省了我们大量的带宽,并且使整个Web应用程序的响应速度更快。



