代码改变世界

BlogEngine中的js和css访问处理

2011-04-17 17:14  MichaelYin  阅读(402)  评论(0编辑  收藏  举报

BlogEngine中将对css和js这种常用资源的访问通过httphandler进行了一次封装,并不是直接请求服务器的文件,服务器读取硬盘上的文件然后返回给客户端,而是将这种常用访问的资源通过缓存存储在了内存中,然后通过缓存依赖检查文件是否被更改,这样带来的好处就是在访问量比较大的时候能够减少读取硬盘的次数和时间,当然实际应用中的效果到底如何由于条件不够,所以本人不能给出实际数据,有条件的朋友可以提供一下。

BlogEngine中的Css文件是和BlogEngine的主题这个功能相关的,主题文件夹下每个相应文件夹下都有一个style.css被site.master所引用,BlogBasePage在运行的时候根据选定的主题的名字加载相应主题下的模板页,模板页中的Head中是有相应的样式表的链接的,然后再BlogBasePage的Onload方法中,通过CompressCss遍历Head中的控件,找到css,然后统一修改css的访问的路径通过httphandler来访问。

		protected virtual void CompressCss()
		{
			if (Request.QueryString["theme"] != null)
				return;

			foreach (Control control in Page.Header.Controls)
			{
				HtmlControl c = control as HtmlControl;
				if (c != null && c.Attributes["type"] != null && c.Attributes["type"].Equals("text/css", StringComparison.OrdinalIgnoreCase))
				{
					if (!c.Attributes["href"].StartsWith("http://"))
					{
						string url = Utils.RelativeWebRoot + "themes/" + BlogSettings.Instance.Theme + "/css.axd?name=" + c.Attributes["href"];
						c.Attributes["href"] = url.Replace(".css", BlogSettings.Instance.Version() + ".css");
						c.EnableViewState = false;
					}
				}
			}
		}

Css处理的handler的名字叫CssHandler,它通过查询字符串来获得需要访问的文件名,然后再缓存中进行查找,没有的话在本地文件中进行查找,并在查找成功后将数据流插入到缓存中去,为了防止文件修改,加入了缓存依赖。

				// In cache?
				if (context.Cache[context.Request.RawUrl] == null)
				{
					// Not found in cache, let's load it up
					if (fileName.StartsWith("http", StringComparison.OrdinalIgnoreCase))
					{
						css = RetrieveRemoteCss(fileName);
					}
					else
					{
						css = RetrieveLocalCss(fileName);
					}
				}
				else
				{
					// Found in cache
					css = (string)context.Cache[context.Request.RawUrl];
				}
SetHeaders方法通过客户端缓存策略进一步提高了性能
            context.Response.Cache.VaryByHeaders["Accept-Encoding"] = true;

            context.Response.Cache.SetExpires(DateTime.Now.ToUniversalTime().AddDays(7));
            context.Response.Cache.SetMaxAge(new TimeSpan(7, 0, 0, 0));
            context.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches);

            string etag = "\"" + hash.ToString() + "\"";
            string incomingEtag = context.Request.Headers["If-None-Match"];

            context.Response.Cache.SetETag(etag);
            context.Response.Cache.SetCacheability(HttpCacheability.Public);

js的处理的JavaScriptHandler和Csshandler基本是差不多的,这里就不在重复了,不过由于js和css又有一点区别。css文件的链接是放在页面的Head里面,所以通过遍历Head统一修改url就可以完成统一请求HttpHandler,而js有点特殊,它可能需要放在页面底部(事实上Blogengine中的脚本引用都是放在底部的,在网上查了一下,据说是下载js会阻塞其他资源的下载,将导致整体响应时间变长),所以js的统一修改访问url是通过AddJavaScriptInclude这个方法来实现的。AddJavaScriptInclude修改js的路径为通过httphandler访问。