更新:之前的版本在Azure上无法正常工作,我已经进行了简化和更正。 (请注意,在使用IIS Express的开发模式下,您需要从Microsoft http://www.iis.net/downloads/microsoft/url-rewrite 安装URL Rewrite 2.0 - 它使用WebPi安装程序,请确保先关闭Visual Studio)
更新:修复了.min文件的规则
最近,我花费了一整天时间尝试让C# / Net 4.6 / MVC 5 / Razor中的自动捆绑(以支持自动版本控制)正常工作。 我阅读了许多关于StackOverflow和其他地方的文章,但我找不到一个端到端的指南来说明如何设置它。 我也不喜欢文件的版本方式(通过将版本查询字符串附加到静态文件请求中 - 即somefile.js?v=1234),因为有些人告诉我某些代理服务器在缓存静态资源时会忽略查询字符串。
因此,在短暂的探索之后,我已经为自动版本控制编写了自己的版本,并包含了完整的说明以使其正常工作。
完整讨论请参考:ASP.NET MVC 5中的简化自动版本控制以解决缓存问题(可在Azure和本地使用,不管是否启用URL Rewrite)
问题:通常在一个项目中会有两种类型的javascript/css文件。
1) 第三方库文件(如jquery或mustache),这些文件很少更改(当更改时,文件的版本通常会更改) - 这些文件可以使用WebGrease或JSCompress.com进行“按需”捆绑/压缩(只需在_Layout.cshtml中包含捆绑文件/版本即可)
2) 页面特定的css/js文件应在新版本构建推送时刷新。(无需用户清除其缓存或进行多次刷新)
我的解决方案是:每次构建项目时自动递增程序集版本,并使用该数字为特定资源上的路由静态文件,以保持其更新(因此将something.js包含为something.v1234.js,其中1234在每次构建项目时自动更改)。我还添加了一些额外的功能,以确保在生产中使用.min.js文件,在调试时使用regular.js文件(我正在使用WebGrease自动化缩小过程)。这个解决方案的一个好处是它可以在本地/开发模式和生产模式下工作。如何实现:每次构建项目时自动递增程序集版本,并使用该数字为特定资源上的路由静态文件,以保持其更新(因此将something.js包含为something.v1234.js,其中1234在每次构建项目时自动更改)。我还添加了一些额外的功能,以确保在生产中使用.min.js文件,在调试时使用regular.js文件(我正在使用WebGrease自动化缩小过程)。这个解决方案的一个好处是它可以在本地/开发模式和生产模式下工作。(我使用的是Visual Studio 2015/Net 4.6,但我相信这也适用于早期版本。)
步骤1: 在编译时启用程序集的自动递增编号
在AssemblyInfo.cs文件中(在项目的“属性”部分找到),更改以下行:
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
to
[assembly: AssemblyVersion("1.0.*")]
步骤2:在web.config中为具有嵌入版本slug的文件设置url重写(请参见步骤3)
在web.config(项目的主要配置文件)中,在system.webServer中添加以下规则。
<rewrite>
<rules>
<rule name="static-autoversion">
<match url="^(.*)([.]v[0-9]+)([.](js|css))$" />
<action type="Rewrite" url="{R:1}{R:3}" />
</rule>
<rule name="static-autoversion-min">
<match url="^(.*)([.]v[0-9]+)([.]min[.](js|css))$" />
<action type="Rewrite" url="{R:1}{R:3}" />
</rule>
</rules>
</rewrite>
步骤三:设置应用程序变量以读取当前程序集版本并在js和css文件中创建版本标识。
在Global.asax.cs文件中(位于项目根目录中),在protected void Application_Start()函数中添加以下代码(在注册行之后)。
string addMin = ".min";
if (System.Diagnostics.Debugger.IsAttached) { addMin = ""; }
Application["JSVer"] = "v" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString().Replace('.','0') + addMin + ".js";
Application["CSSVer"] = "v" + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString().Replace('.', '0') + addMin + ".css";
步骤 4:使用我们在 Global.asax.cs 中设置的应用程序变量更改 Razor 视图中的 src 链接。
@HttpContext.Current.Application["CSSVer"]
@HttpContext.Current.Application["JSVer"]
例如,我的_Layout.cshtml文件中,在头部区域,我有以下的代码块来引入样式表:
<!-- Load all stylesheets -->
<link rel='stylesheet' href='https://fontastic.s3.amazonaws.com/8NNKTYdfdJLQS3D4kHqhLT/icons.css' />
<link rel='stylesheet' href='/Content/css/main-small.@HttpContext.Current.Application["CSSVer"]' />
<link rel='stylesheet' media='(min-width: 700px)' href='/Content/css/medium.@HttpContext.Current.Application["CSSVer"]' />
<link rel='stylesheet' media='(min-width: 700px)' href='/Content/css/large.@HttpContext.Current.Application["CSSVer"]' />
@RenderSection("PageCSS", required: false)
这里有几个需要注意的地方:1)文件没有扩展名。2)也没有.min扩展名。这两个都由Global.asax.cs中的代码处理。
同样,在我的javascript部分(也在_Layout.cs中),我有以下代码:
<script src="~/Scripts/all3bnd100.min.js" type="text/javascript"></script>
<script src="~/Scripts/ui.@HttpContext.Current.Application["JSVer"]" type="text/javascript"></script>
@RenderSection("scripts", required: false)
第一个文件是我手动使用WebGrease创建的所有第三方库的捆绑包。如果我添加或更改了捆绑包中的任何文件(这很少见),那么我会手动将文件重命名为all3bnd101.min.js、all3bnd102.min.js等等...此文件与重写处理程序不匹配,因此将保留在客户端浏览器上缓存,直到您手动重新捆绑/更改名称。
第二个文件是ui.js(根据您是否在调试模式下运行,将编写为ui.v12345123.js或ui.v12345123.min.js)。这将被处理/重写。(您可以在Global.asax.cs的Application_OnBeginRequest中设置断点以查看它的工作情况)
有关此问题的完整讨论,请参见:
ASP.NET MVC 5中简化Javascript / CSS自动版本控制以解决缓存问题的方法(可在Azure和本地使用)(包括一种无需URL重写的方法)