为客户端缓存文件添加版本号

大部分的浏览器都支持缓存功能,但这也是柄双刃剑,好的一面是它可以有效地缓解服务器的压力,不好的一面是当服务器上某个文件(比如js,css)发生变更时,由于浏览器的缓存导致文件没有更新成功。

用户是不会知道变更的,也不会去清理缓存。因此会有一系列的麻烦出现,如何才能有效地解决这个问题呢?

很简单,浏览器支持在文件后面加上?version=xxx,就可以知道当前的文件是从本地获取还是从服务器获取。只要访问的版本号发生了变化,那么就会从服务器上获取更新。

每次从配置文件去读取版本号,有点劳民伤财的意思,除非你有特殊需求,最好可以支持部署时自动生成版本号。以下代码可以实现,根据当前程序集的发布时间作为版本号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public static class VersionUtils
{
public readonly static DateTime VersionDate;

public readonly static Int32 VersionNumber;

static VersionUtils()
{

VersionDate = System.IO.File.GetLastWriteTime(typeof(VersionUtils).Assembly.Location);
VersionNumber = Int32.Parse(VersionDate.ToString("yyyyMMddHHmm"));
}
}

public static class HtmlHelperExtension
{
public static MvcHtmlString Script(this HtmlHelper html, string contentPath)
{

return VersionedContent(html, "<script src=\"{0}\" type=\"text/javascript\"></script>", contentPath);
}

public static MvcHtmlString Style(this HtmlHelper html, string contentPath)
{

return VersionedContent(html, "<link href=\"{0}\" rel=\"stylesheet\" type=\"text/css\">", contentPath);
}

private static MvcHtmlString VersionedContent(this HtmlHelper html, string template, string contentPath)
{

contentPath = UrlHelper.GenerateContentUrl(contentPath, html.ViewContext.HttpContext) + "?v=" + VersionUtils.VersionNumber;
return MvcHtmlString.Create(string.Format(template, contentPath));
}
}

public static class UrlHelperExtension
{
public static string ContentVersioned(this UrlHelper urlHelper, string contentPath)
{

return String.Format("{0}?v={1}", urlHelper.Content(contentPath), VersionUtils.VersionNumber);
}

}

使用方法

1
2
3
<link href="@Url.ContentVersioned("~/Content/Site.css")" rel="stylesheet" type="text/css" />
@Html.Style("~/Content/bootstrap.css");
@Html.Script("~/Scripts/angular.js");

参考文章

https://github.com/yuanrui/blog/issues/1

avatar

chilihotpot

You Are The JavaScript In My HTML