日期:2014-05-16  浏览次数:20883 次

ASP.NET 4.5 Bundle组件(捆绑、缩小静态文件)

阅读目录:

  • 1.开篇介绍
  • 2.System.Web.Optimization 组件
  • 3.System.Web.Optimization 组件基本原理
  • 4.扩展自定义类型静态文件

1】开篇介绍

这篇文章将简单的分析一下有关静态文件捆绑的ASP.NET组件System.Web.Optimization的运行原理及基本的缓存问题;

在我们的项目里面充斥着很多静态文件,为了追求模块化、插件化很多静态文件都被设计成模块的方式或者被分解,在需要的时候在通过组合的方式在UI层上使用;这就带来一个问题,文件多了会影响浏览器加载页面的速度,而且由于浏览器的并发限制,对于并行的请求不是无限制的,所以捆绑静态文件的功能就产生;其实在以前,IIS还没有集成管道模型的时候我们只能通过动态资源的方式进行输出,也就是我们经常在*aspx页面里看见很多*.axd结尾的请求,当然多数情况下是配合ASP.NETAJAX用来输出动态JS、HTMDOM、CSS用的;

最新的IIS已经很好的集成了ASP.NET管道模型,也就是说我们完全可以通过ASP.NET本身的扩展来控制所有经过IIS的请求,包括静态文件,所以让捆绑静态文件成为了可能;

下面我们将分析一下System.Web.Optimization组件的基本运行原理,它是如何动态加载的,如何控制缓存的;

2】System.Web.Optimization 组件

每当我们新建一个ASP.NETMVC4站点的时候都会在~/App_Start目录下有一个BundleConfig.cs的启动文件,当然创建其他的ASP.NET4.0及4.0以上的项目也会有;

我第一次看见这个文件实在让我困惑,所以我打算简单的分析一下,知道其基本原理;

代码是一个静态方法,然后传入一个BundleCollection集合对象,其实就是Bundle对象的集合,然后通过向集合内部注册多个Bundle;每个Bundle对应着多个静态文件,可以想象成就是键值对集合;通过后面的Include方法包含N多个静态文件,这里的静态文件路径可以是符合特定规则的字符串,由它内部去计算;

这是注册阶段,然后就是使用阶段,使用阶段很简单只要我们通过我们注册的Key字符串就能直接引用这些静态文件列表;

我们只要关注Styles.Render、Scripts.Render两个方法,这两个方法是想页面注入之前在后台配置的静态文件列表;这样我们在客户端看见的就是被捆绑过后的文件集合了;

文件的连接地址已经是被捆绑过后的地址了,这个地址就是我们在之前注册的时候用的key,后面它需要这个key去获取value 静态文件列表;要想你的捆绑起效果需要在注册的时候加上一段:BundleTable.EnableOptimizations = true;代码,意思是说开启捆绑,如果不开启捆绑则默认在调试环境里将不起效果,因为System.Web.Optimization使用了默认捆绑策略,如果是在Debug模式下,将不启用捆绑,如果你人为的设置了将覆盖默认设置;

使用就是这些,下面我们需要搞懂它是如何运行的,要了解一下它的基本原理;

3】System.Web.Optimization 组件基本原理

既然IIS集成了管道模型,那么我们肯定是能找到对应的HttpModule的,为了节省时间我就不去下载源码了,我们直接用反编译工具看一下;

这就是Bundle的HttpModule,它只用来处理 Bundle的连接地址,虽然它在HTTP的管道中;找到它就好顺藤摸瓜了,但是奇怪的是我在Web.config里没有发现它的配置信息,奇怪了,难道它还跑去系统文件改,当然是不可能的;所以我一时还想不起能有什么办法动态注册,提起动态注册突然有了思路,好像有一个Assembly级别的特性用来注册Application_Start启动时候的前置代码,会在Application启动之前执行,来看一下;

果然藏着这里呢,它注册了一个PreApplicationStartCode静态类,使用Start方法启动;

这段代码很简单,先判断有没有执行过注册,如果没有就执行动态注册,这个动态注册组件是.NETFramework自带的,在Microsoft.Web.Infrastructure里面只不过属于平台相关的,跟ASP.NET没有直接关系,我们可以用Microsoft.Web.Infrastructure来开发自己的WEB组件;这里有一个疑问,为什么静态方法也要加判断呢,不是只会执行一次吗,因为静态方法的执行是不受控制的,所以如果不加判断很有可能会注册多次,出于严谨考虑还是加上;

现在基本上我们已经找到源头了,服务端这里我们先放一下,对于客户端的疑问很多,它既然帮我们捆绑了,那么缓存是如何处理的,也就是说它的输出缓存有没有设置,如果设置了不是有问题;