在客户端机器上刷新缓存的脚本文件



我们的一个生产基地遇到了问题。JavaScript文件被更新为一个页面并上传到IIS。我们使用

直接包含文件
<script src="PATH_TO_SCRIPT" type="text/javascript"></script>

我们开始收到客户的投诉,说页面坏了。这是因为JS文件缓存在客户端机器上,没有从服务器刷新。

我们如何避免这种情况下不改变javascript文件名在未来?

ASP。网络捆绑和缩小可能会有所帮助。但是有很多网页和网站是相当遗留的。几乎所有的页面都有一些沉重的逻辑写在相关的js文件中。

网站运行的是。net 4.0和IIS 7

捆绑和缩小确实是处理这个问题的正确方法,因为它会在渲染脚本时正确地向url添加正确的版本号。

但是,如果这是一个遗留站点,并且由于某些原因您不能使用捆绑,那么一种可能性是编写一个服务器端帮助程序,它将生成脚本标记并计算文件的校验和,并附加适当的查询字符串参数:

public static class ScriptExtensions
{
    public static string Script(this Page page, string relativeUrl)
    {
        var path = page.Server.MapPath(relativeUrl);
        if (File.Exists(path))
        {
            return string.Format(
                "<script type="type/javascript" src="{0}?v={1}"></script>",
                page.ResolveUrl(relativeUrl),
                Hash(path)
            );
        }
        return string.Empty;
    }
    private static string Hash(string file)
    {
        using (var stream = File.OpenRead(file))
        using (var bs = new BufferedStream(stream))
        {
            using (var sha1 = new SHA1Managed())
            {
                byte[] hash = sha1.ComputeHash(bs);
                var result = new StringBuilder(2 * hash.Length);
                foreach (byte b in hash)
                {
                    result.AppendFormat("{0:X2}", b);
                }
                return result.ToString();
            }
        }
    }
}

,然后在你的WebForm中使用帮助器来包含你的脚本:

<%= this.Script("~/scripts/example.js") %>

,它将发出以下标记:

<script type="type/javascript" src="/scripts/example.js?v=3C222D8DFA2A02A02E9A585EA6FE0D95673E8B4A"></script>

现在,当你改变脚本文件的内容,它的SHA1校验和将是不同的,一个不同的版本查询字符串参数将生成和附加破坏所有客户端缓存。

受Darin解决方案的启发,我决定使用捆绑和缩小来获得它所提供的所有好处,我想出了以下解决方案。为Page类型添加一个带有Extension方法的静态类:

public static class ScriptExtensions
{
    public static string Script(this Page page, string relativeUrl)
    {
        var path = page.Server.MapPath(relativeUrl);
        if (File.Exists(path))
        {
            return BundlesConfig.AddPageScript(relativeUrl);
        }
        return string.Empty;
    }
}

BundlesConfig类包含为js文件生成bundle和添加到Bundles的方法:

public class BundlesConfig
{
    private static readonly ICollection<string> addedScripts 
                                                     = new HashSet<string>();
    private static readonly string bundleTemplate = "~/bundles/scripts/{0}";
    internal static string AddPageScript(string relativeUrl)
    {            
            var fileName = CleanFileName(relativeUrl);
            var bundleName = string.Format(bundleTemplate, fileName);
            if(!addedScripts.Contains(fileName))
            {
                var bundle = new ScriptBundle(bundleName);
                bundle.Include(relativeUrl);
                addedScripts.Add(fileName);
                BundleTable.Bundles.Add(bundle);
            }
      return System.Web.Optimization.Scripts.Render(bundleName).ToHtmlString();
    }
    private static string CleanFileName(string url)
    {
        if (url.Contains("/"))
        {
            return url.Substring(url.LastIndexOf("/") + 1).Replace('.', '_')
                          .Replace("-", "__");
        }
        return url.Replace('.', '_').Replace("-", "__");
    }
}

现在在页面上代替标准的script标签:

<scrip type="text/javascript" src="/scripts/jquery-min.js"></script>
我们使用

:

<%= this.Script("~/Scripts/jquery-min.js") %>

方法吐出以下内容:

<script type="text/javascript" src="/bundles/scripts/jquery__min_js?v=...."></script>

最新更新