如何强制浏览器使用版本控制重新加载缓存的静态文件?

Ham*_*asi 10 c# asp.net asp.net-mvc caching browser-cache


部署网站的新版本后,浏览器会从旧网页的缓存中加载所有内容,直到完成硬性强制刷新。

ASP.NET MVC该文件成为捆绑,它通过优化框架处理。添加到您的文件链接的版本,如果您的包文件发生更改,则会生成新令牌。按照下面的代码:

例如,js文件名是:datatables

当你把它放在同名的包中时,你会看到

datatables?v=anY9_bo7KitrGnXQr8ITP3ylmhQe9NDzSjgLpLQWQFE1
Run Code Online (Sandbox Code Playgroud)

作为文件名。更改datatables并在浏览器中再次查看文件名,肯定会更改:

datatables?v=r8yhQBxKyDgrOGyqr1ndtdG92Ije09nqTY7yogrOSTk1
Run Code Online (Sandbox Code Playgroud)

但是有两个问题:

  • 如果我们的文件不在 Bundle 中,我们该怎么办?
  • 是一种强制浏览器刷新缓存的方法吗?

Ham*_*asi 8

我们有一种解决方案,但有一些不同的实施方式。我们使用上面的解决方案。

datatables?v=1
Run Code Online (Sandbox Code Playgroud)

我们可以处理文件的版本,这意味着每次我们更改文件时,也要更改它的版本。但这不是一个合适的方式。

另一种使用指南的方式,它也不适合,因为每次它获取文件时都不会从浏览器缓存中使用。

datatables?v=Guid.NewGuid()
Run Code Online (Sandbox Code Playgroud)

最后一种方式是最好的方式是:

当发生文件更改时,也要更改版本。检查以下代码:

<script src="~/scripts/main.js?v=@File.GetLastWriteTime(Server.MapPath("/scripts/main.js")).ToString("yyyyMMddHHmmss")"></script>
Run Code Online (Sandbox Code Playgroud)

通过这种方式,当您更改文件时,LastWriteTime也会更改,因此文件的版本会更改,并且在接下来打开浏览器时,它会检测到一个新文件并获取它。


Rez*_*aei 5

Assuming you cannot use bundling for some reason, the solution suggested by the original poster is good enough, however it's better to put the logic inside a helper method.

It makes the code testable, it helps to change the logic without changing .cshtml , and also helps to not repeat the filename twice. Then you can have have a much cleaner code:

<script src="@Url.ContentWithVersion("~/scripts/main.js")"></script>
Run Code Online (Sandbox Code Playgroud)

To do so, you can add ContentWithVersion extension method to the existing UrlHelper:

using System;
using System.IO;
using System.Web;
using System.Web.Mvc;
public static class UrlHelperExtensions
{
    public static string ContentWithVersion(this UrlHelper urlHelper, string path)
    {
        if (urlHelper == null)
            throw new ArgumentNullException(nameof(urlHelper));
        var result = urlHelper.Content(path);
        var file = HttpContext.Current.Server.MapPath(path);
        if (File.Exists(file))
            result += $"?v={File.GetLastWriteTime(file).ToString("yyyyMMddHHmmss")}";
        return result;
    }
}
Run Code Online (Sandbox Code Playgroud)