0

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

<script src="PATH_TO_SCRIPT" type="text/javascript"></script>

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

我们以后如何在不更改javascript文件名的情况下避免这种情况?

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

该站点正在运行 .Net 4.0 和 IIS 7

4

2 回答 2

2

捆绑和缩小确实是处理此问题的正确方法,因为它会在呈现脚本时负责正确地将正确的版本号附加到 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 校验和将有所不同,并且将生成不同版本的查询字符串参数并附加到所有客户端缓存中。

于 2013-03-30T11:09:58.193 回答
0

受到 Darin 解决方案的启发,我决定使用 Bundling and Minification 以获得它所提供的所有好处的好处,我想出了以下解决方案。为 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;
    }
}

BundlesConfigcontians 方法为 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>
于 2013-04-03T04:57:31.537 回答