背景

  作为web开发人员大家大多了解一些网站的性能优化方法,其实大部分方法都不复杂,例如针对前端js和css的压缩来减少请求大小,通过合并来减少请求次数。这里站在.Net后端程序员的角度来看一下如何最简单快捷的处理这一类需求。

  全文分3节 combres,mvc4的Bundle,以及2者的对比和个人的意见观点。


Combres

  Combres是一个.NET程序库,能够缩小,压缩,合并,以及缓存的JavaScript和CSS资源,ASP.NET和ASP.NET MVC的Web应用程序。简单地说,它可以帮助您的应用程序更好的页面加载速度。

  源代码存在https://github.com/buunguyen/combres

  通过nuget添加combres非常简单

  

  加载完成后 .Net3.5的同学需要按照combres.readme的指导,首先删除掉AppStart_Combres.cs然后在global.asax中添加Combres引用,然后在RegisterRoutes()或者Application_Start()添加方法RouteTable.Routes.AddCombresRoute("Combres")

  .Net4.0的同学可以忽略这一步,你们会在发现nuget包安装程序(下面简称包管理)已经自动帮你们生成了这样一段代码

publicstaticclassCombres{publicstaticvoidPreStart(){RouteTable.Routes.AddCombresRoute("Combres");}}

  下面最主要的就是就是配置combres.xml,至于webconfig的配置包管理已经帮大家设置完成。

  为了方便测试,我们建个白板页面,然后添加最简单的js文件和css文件。

  

  那么下面来看测试效果,我们先建一个简单的测试页面。

@{

ViewBag.Title = "Home Page";

}

<script src="~/Scripts/Demo/JScript1.js" type="text/javascript"></script>

<script src="~/Scripts/Demo/JScript2.js" type="text/javascript"></script>

<script src="~/Scripts/Demo/JScript3.js" type="text/javascript"></script>

<link href="~/Content/Demo/StyleSheet1.css" rel="stylesheet" type="text/css" />

<link href="~/Content/Demo/StyleSheet2.css" rel="stylesheet" type="text/css" />

<link href="~/Content/Demo/StyleSheet3.css" rel="stylesheet" type="text/css" />


  打开fiddler查看页面请求。

  

  然后我们使用combres修改页面代码

  mvc: 

1@usingCombres.Mvc2@{3ViewBag.Title="HomePage";4}5@Url.CombresLink("siteCss")6@Url.CombresLink("siteJs")

  webform:

1<%=WebExtensions.CombresLink("siteJs")%>2<%=WebExtensions.CombresLink("siteCss")%>

  再来查看页面请求

  

  请求次数变为了2次,大小也被压缩的非常低。

  Combres的实现原理不复杂,服务器端先加载配置缓存起来,根据配置节点生成hash值,具体实现如下 

1publicstringGenerate(ResourceSetrs)2{3if(Log.IsDebugEnabled)4Log.Debug("Computinghashforset"+rs.Name+".Currenthash:"+rs.Hash);56varcontributingFactors=newList<object>{rs.DebugEnabled};7rs.Filters.ToList().ForEach(contributingFactors.Add);8rs.CacheVaryProviders.ToList().ForEach(contributingFactors.Add);9rs.Resources.ToList().ForEach(r=>10{11contributingFactors.Add(r.ReadFromCache(true));12contributingFactors.Add(r.ForwardCookie);13contributingFactors.Add(r.Mode);14contributingFactors.Add(r.Minifier);15});16varhash=contributingFactors.Select(f=>f.GetHashCode())17.Aggregate(17,(accum,element)=>31*accum+element)18.ToString();1920if(Log.IsDebugEnabled)21Log.Debug("Newhash:"+hash);22returnhash;23}

  得出来的值就是我们上面看到的combres.xsd/setname/hashvalue中的hashvalue,当我们请求产生的时候会由一个CombresHandler根据hashvalue来获取对应的资源并且进行合并压缩。

  处理流程首先判断你的浏览器是否支持压缩,通过Context.Request.Headers["Accept-Encoding"]。

  如果判断为接受combres会对资源进行2层压缩,我们这里简单称只为minifier和gzip。

  如果浏览器不支持压缩那么gzip这一层会被忽略,minifier的压缩方法使用YuiJSMinifier和YuiCssMinifier,方法依赖雅虎的开源组件Yahoo.Yui.Compressor

  

  handler会为新的请求生成一个cachekey:&ldquo;Combres/Combres.RequestProcessor/siteJs/1342767128/gzip&rdquo;

  和etag key&ldquo;Combres/Combres.RequestProcessor/siteJs/1342767128/gzip/@etag&rdquo;(实际上真正存于Context.Response.Cache的ETag是"1342767128")

  分别对应服务器端缓存和浏览器缓存,当下次请求已经发现有key存在,便从缓存中直接获取资源或者直接304。

  根据结果图来看,combres确实是一款很不错的工具。


MVC4的Bundle

  MVC4以后自带了Bundling和Minification。操作也很简单,新建一个mvc4项目。在App_Start文件夹下找到BundleConfig.cs。

  添加如下代码:

1publicstaticvoidRegisterBundles(BundleCollectionbundles)2{34bundles.Add(newScriptBundle("~/bundles/jquerydemo").Include(5"~/Scripts/Demo/JScript1.js",6"~/Scripts/Demo/JScript2.js",7"~/Scripts/Demo/JScript3.js"));89bundles.Add(newStyleBundle("~/Content/cssdemo").Include(10"~/Content/Demo/StyleSheet1.css",11"~/Content/Demo/StyleSheet2.css",12"~/Content/Demo/StyleSheet3.css"));13}

  页面端添加:

1@Styles.Render("~/Content/cssdemo")2@Scripts.Render("~/bundles/jquerydemo")

  然后记住在BundleConfig.cs添加BundleTable.EnableOptimizations = true;不然MVC4不会启用压缩,减少请求数量和带宽。

  我们来看一下效果图:

  

  请求次数减少,也有压缩。但是比起combres效率要差了一些。但是这样未必就是说combres要更好。


对比

  2者相比较而已combres的效率要高一些,但是mvc4作为原生自带的功能,对于版本管理比较苛刻的系统还是具有优势,并且对于大型项目还要涉及到cdn问题。

  目前combres是不支持cdn的,虽然作者给出了相关的话题,但是作者本人最后还有给出了不是令人满意的答复。

  

  相对MVC4的Bundle是支持cdn的,只需要在对应节点添加bundles.UseCdn = true即可。

  所以根据各自项目不同的场景,酌情处理吧。

  个人推荐静态资源的压缩和合并尽量在前端就做掉,例如grunt。这样不管是cdn还是部署发布都更合理没有必要再浪费后端的处理资源。


本篇先到此,希望对大家有帮助!