我们的一个生产基地遇到了问题。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>