首页 > 程序开发 > web前端 > JavaScript >

js文件合并,压缩,缓存,延迟加载

2012-05-03

做web前段也有一段时间了,对于web中js文件的加载有些体会想跟大家一起分享一下。1.首先说说js文件的合并和压缩吧为了便于集中式管理js的合并和压缩我们创建一个Js.ashx文件来专门处理合并压缩代码如下:[csharp...

做web前段也有一段时间了,对于web中js文件的加载有些体会想跟大家一起分享一下。

1.首先说说js文件的合并和压缩吧

为了便于集中式管理js的合并和压缩我们创建一个Js.ashx文件来专门处理合并压缩

代码如下:

[csharp]
public class Js : IHttpHandler
{

public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/javascript";
HttpRequest request = context.Request;
HttpResponse response = context.Response;
if (!request.QueryString.AllKeys.Contains("href"))
{
response.Write("No Content");
}
else
{
string href = context.Request.QueryString["href"].Trim();
string[] files = href.Split(new string[]{",",","},StringSplitOptions.RemoveEmptyEntries);
foreach (string fileName in files)
{
string filePath = context.Server.MapPath(fileName);
if (File.Exists(filePath))
{
string content = File.ReadAllText(filePath, Encoding.UTF8);
content = JavaScriptCompressor.Compress(content);
response.Write(content);
}
else
{
response.Write("\r\n未找到源文件"+filePath+"\r\n");
}
}
}
}

public bool IsReusable
{
get
{
return false;
}
}
}
当我们在浏览器访问js时如:
http://localhost:58798/js.ashx?href=scripts/jquery.lazyload.js,scripts/jquery.validate.js



返回结果如图:

但是在实际开发中很多项目为了最求js的合并和压缩,开发很不友好把js的引用放在一个地方,写了很长的一串啊,如上面js引用。

下面说说如何改善吧:
[csharp]
public static class Extensions
{
const string jsFileKey = "JSFileKey";
static string jshandlerUrl = string.Empty;
public static string JsHandlerUrl
{
get
{
if (string.IsNullOrEmpty(jshandlerUrl))
{
jshandlerUrl = ConfigurationManager.AppSettings["jsHandlerUrl"] ?? string.Empty;
}
return jshandlerUrl;
}
}

public static void AppendJsFile(this HtmlHelper htmlHelper, string jsFile, int group = 1)
{
NameValueCollection jsFiles = null;
if (htmlHelper.ViewContext.HttpContext.Items.Contains(jsFileKey))
{
jsFiles = htmlHelper.ViewContext.HttpContext.Items[jsFileKey] as NameValueCollection;
}
else
{
jsFiles = new NameValueCollection();
htmlHelper.ViewContext.HttpContext.Items.Add(jsFileKey, jsFiles);
}
if (jsFiles.AllKeys.Contains(group.ToString()))
{
string fileUrl = jsFiles[group.ToString()];
if (!fileUrl.Contains(jsFile))
jsFiles.Add(group.ToString(), jsFile);
}
else
{
jsFiles.Add(group.ToString(), jsFile);
}

htmlHelper.ViewContext.HttpContext.Items[jsFileKey] = jsFiles;
}

public static MvcHtmlString RenderJsFile(this HtmlHelper htmlHelper)
{
NameValueCollection jsFiles = null;
StringBuilder content = new StringBuilder();
if (htmlHelper.ViewContext.HttpContext.Items.Contains(jsFileKey))
{
jsFiles = htmlHelper.ViewContext.HttpContext.Items[jsFileKey] as NameValueCollection;
List<string> jsKeys = jsFiles.AllKeys.OrderBy(x => x).ToList<string>();

string jsFormat = "<script type=\"text/javascript\" src=\"{0}\"></script>";
foreach (string key in jsKeys)
{
string jsFile = jsFiles[key];
content.AppendFormat(jsFormat, JsHandlerUrl + jsFile);
//htmlHelper.ViewContext.HttpContext.Response.Write(string.Format(jsFormat, JsHandlerUrl + jsFile));
}
}
return new MvcHtmlString(content.ToString());
}
}
这样在开发的时候我们书写代码就很方便了如:
[csharp]
@{Html.AppendJsFile("Scripts/jquery.lazyload.js");}
下面我们来看看js的延迟加载,为了实现js延迟加载我们需要引用相关的js,在这里我用的是lazyload.js,具体请参考http://www.2cto.com/kf/201205/130023.html

延迟加载后的效果

在文档加载前只加载了一个2.2k的lazyload.js文件,其他的js文件都在ready后加载。
下面再来看看js的缓存吧,缓存涉及到要做服务端和客户端缓存

修改后的代码:

[csharp]
class CacheItem
{
public string Content { set; get; }
public DateTime Expires { set; get; }
}
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/javascript";
HttpRequest request = context.Request;
HttpResponse response = context.Response;
if (!request.QueryString.AllKeys.Contains("href"))
{
response.Write("No Content");
}
else
{
string href = context.Request.QueryString["href"].Trim();
string[] files = href.Split(new string[] { ",", "," }, StringSplitOptions.RemoveEmptyEntries);
CacheItem item = null;
object obj = HttpRuntime.Cache.Get(href);//服务端缓存
if (null == obj)
{
StringBuilder allText = new StringBuilder();
foreach (string fileName in files)
{
string filePath = context.Server.MapPath(fileName);
if (File.Exists(filePath))
{
string content = File.ReadAllText(filePath, Encoding.UTF8);
content = JavaScriptCompressor.Compress(content);
//response.Write(content);
allText.Append(content);
}
else
{
// response.Write("\r\n未找到源文件"+filePath+"\r\n");
allText.Append("\r\n未找到源文件" + filePath + "\r\n");
}
}//end foreach
item = new CacheItem() { Content = allText.ToString(), Expires = DateTime.Now.AddHours(1) };
HttpRuntime.Cache.Insert(href, item, null, item.Expires, TimeSpan.Zero);
}
else
{
item = obj as CacheItem;
}
if (request.Headers["If-Modified-Since"] != null && TimeSpan.FromTicks(item.Expires.Ticks - DateTime.Parse(request.Headers["If-Modified-Since"]).Ticks).Seconds < 100)
{
response.StatusCode = 304;
// response.Headers.Add("Content-Encoding", "gzip");
response.StatusDescription = "Not Modified";
}
else
{
response.Write(item.Content);
SetClientCaching(response, DateTime.Now);
}
}//end else href
}
private void SetClientCaching(HttpResponse response, DateTime lastModified)
{
response.Cache.SetETag(lastModified.Ticks.ToString());
response.Cache.SetLastModified(lastModified);
//public 以指定响应能由客户端和共享(代理)缓存进行缓存。
response.Cache.SetCacheability(HttpCacheability.Public);
//是允许文档在被视为陈旧之前存在的最长绝对时间。
response.Cache.SetMaxAge(new TimeSpan(7, 0, 0, 0));
//将缓存过期从绝对时间设置为可调时间
response.Cache.SetSlidingExpiration(true);
}
运行效果如图:
代码下载地址:http://up.2cto.com/2012/0503/20120503021534861.zip




摘自 dz45693的专栏



相关文章
最新文章
热点推荐