javascript 版本(asp-附加版本)如何在 ASP.NET 核心 MVC 中工作?
How does javascript version (asp-append-version) work in ASP.NET Core MVC?
新的 MVC () 似乎不支持动态捆绑,应该使用 gulp 任务来完成。 MVC 支持一些名为 asp-append-version
的新属性,但我还没有找到关于它如何工作的任何解释。我怀疑它正在计算文件内容的一些哈希值,甚至在文件更改后更新它。有没有关于它如何工作的文档?
我还想知道它是如何检测文件更改的,或者它是否只是在每次 MVC 解析 razor 标记时重新计算哈希值。
您可以查看 LinkTagHelper
source code, where you will see it is basically adding a version query string to the href value via a FileVersionProvider
:
if (AppendVersion == true)
{
EnsureFileVersionProvider();
if (Href != null)
{
output.Attributes[HrefAttributeName].Value = _fileVersionProvider.AddFileVersionToPath(Href);
}
}
private void EnsureFileVersionProvider()
{
if (_fileVersionProvider == null)
{
_fileVersionProvider = new FileVersionProvider(
HostingEnvironment.WebRootFileProvider,
Cache,
ViewContext.HttpContext.Request.PathBase);
}
}
FileVersionProvider
将使用SHA256
算法 计算文件内容的哈希值。然后它将 url 对其进行编码并将其添加到查询字符串中,如:
path/to/file?v=B95ZXzHiOuQJzhBoHlSlNyN1_cOjJnz2DFsr-3ZyyJs
仅当文件更改时才会重新计算哈希值,因为它已添加到缓存但具有基于文件观察器的过期触发器:
if (!_cache.TryGetValue(path, out value))
{
value = QueryHelpers.AddQueryString(path, VersionKey, GetHashForFile(fileInfo));
var cacheEntryOptions = new MemoryCacheEntryOptions().AddExpirationToken(_fileProvider.Watch(resolvedPath));
_cache.Set(path, value, cacheEntryOptions);
}
此观察器由 HostingEnvironment.WebRootFileProvider
提供,它实现了 IFileProvider
:
//
// Summary:
// Creates a change trigger with the specified filter.
//
// Parameters:
// filter:
// Filter string used to determine what files or folders to monitor. Example: **/*.cs,
// *.*, subFolder/**/*.cshtml.
//
// Returns:
// An Microsoft.Framework.Caching.IExpirationTrigger that is triggered when a file
// matching filter is added, modified or deleted.
IExpirationTrigger Watch(string filter);
注意:您可以通过检查 IMemoryCache
:
中的值自己查看缓存的值
//give the link:
<link rel="stylesheet" asp-append-version="true" href="~/css/site.css" />
//You can check the cached version
this.Context.RequestServices.GetRequiredService<IMemoryCache>().Get("/css/site.css")
//Which will show a value like:
/css/site.css?v=B95ZXzHiOuQJzhBoHlSlNyN1_cOjJnz2DFsr-3ZyyJs
根据FileVersionProvider的当前实现,哈希仅添加到相对文件路径,例如<script src="~/js/jquery.min.js" asp-append-version="true"></script>
如果使用绝对路径,例如https://code.jquery.com/jquery-3.1.1.js
,不会添加哈希。
ASP.NET 核心 2.2 及更高版本
剃刀
@{var fileVersion = Context.AddFileVersionToPath("./path/to/resource");}
<script src="@fileVersion"></script>;
扩展方法
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.Extensions.DependencyInjection;
public static class HttpContextExtensions
{
public static string AddFileVersionToPath(this HttpContext context, string path)
{
return context
.RequestServices
.GetRequiredService<IFileVersionProvider>()
.AddFileVersionToPath(context.Request.PathBase, path);
}
}
ASP.NET Core 2.1 及更早版本
剃刀
var fileversion = '@this.AddFileVersionToPath("/js/components/forms.js")';
扩展方法
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.TagHelpers.Internal;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
public static class IRazorPageExtensions
{
public static string AddFileVersionToPath(this IRazorPage page, string path)
{
var context = page.ViewContext.HttpContext;
IMemoryCache cache = context.RequestServices.GetRequiredService<IMemoryCache>();
var hostingEnvironment = context.RequestServices.GetRequiredService<IHostingEnvironment>();
var versionProvider = new FileVersionProvider(hostingEnvironment.WebRootFileProvider, cache, context.Request.Path);
return versionProvider.AddFileVersionToPath(path);
}
}
新的 MVC (asp-append-version
的新属性,但我还没有找到关于它如何工作的任何解释。我怀疑它正在计算文件内容的一些哈希值,甚至在文件更改后更新它。有没有关于它如何工作的文档?
我还想知道它是如何检测文件更改的,或者它是否只是在每次 MVC 解析 razor 标记时重新计算哈希值。
您可以查看 LinkTagHelper
source code, where you will see it is basically adding a version query string to the href value via a FileVersionProvider
:
if (AppendVersion == true)
{
EnsureFileVersionProvider();
if (Href != null)
{
output.Attributes[HrefAttributeName].Value = _fileVersionProvider.AddFileVersionToPath(Href);
}
}
private void EnsureFileVersionProvider()
{
if (_fileVersionProvider == null)
{
_fileVersionProvider = new FileVersionProvider(
HostingEnvironment.WebRootFileProvider,
Cache,
ViewContext.HttpContext.Request.PathBase);
}
}
FileVersionProvider
将使用SHA256
算法 计算文件内容的哈希值。然后它将 url 对其进行编码并将其添加到查询字符串中,如:
path/to/file?v=B95ZXzHiOuQJzhBoHlSlNyN1_cOjJnz2DFsr-3ZyyJs
仅当文件更改时才会重新计算哈希值,因为它已添加到缓存但具有基于文件观察器的过期触发器:
if (!_cache.TryGetValue(path, out value))
{
value = QueryHelpers.AddQueryString(path, VersionKey, GetHashForFile(fileInfo));
var cacheEntryOptions = new MemoryCacheEntryOptions().AddExpirationToken(_fileProvider.Watch(resolvedPath));
_cache.Set(path, value, cacheEntryOptions);
}
此观察器由 HostingEnvironment.WebRootFileProvider
提供,它实现了 IFileProvider
:
//
// Summary:
// Creates a change trigger with the specified filter.
//
// Parameters:
// filter:
// Filter string used to determine what files or folders to monitor. Example: **/*.cs,
// *.*, subFolder/**/*.cshtml.
//
// Returns:
// An Microsoft.Framework.Caching.IExpirationTrigger that is triggered when a file
// matching filter is added, modified or deleted.
IExpirationTrigger Watch(string filter);
注意:您可以通过检查 IMemoryCache
:
//give the link:
<link rel="stylesheet" asp-append-version="true" href="~/css/site.css" />
//You can check the cached version
this.Context.RequestServices.GetRequiredService<IMemoryCache>().Get("/css/site.css")
//Which will show a value like:
/css/site.css?v=B95ZXzHiOuQJzhBoHlSlNyN1_cOjJnz2DFsr-3ZyyJs
根据FileVersionProvider的当前实现,哈希仅添加到相对文件路径,例如<script src="~/js/jquery.min.js" asp-append-version="true"></script>
如果使用绝对路径,例如https://code.jquery.com/jquery-3.1.1.js
,不会添加哈希。
ASP.NET 核心 2.2 及更高版本
剃刀
@{var fileVersion = Context.AddFileVersionToPath("./path/to/resource");}
<script src="@fileVersion"></script>;
扩展方法
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.Extensions.DependencyInjection;
public static class HttpContextExtensions
{
public static string AddFileVersionToPath(this HttpContext context, string path)
{
return context
.RequestServices
.GetRequiredService<IFileVersionProvider>()
.AddFileVersionToPath(context.Request.PathBase, path);
}
}
ASP.NET Core 2.1 及更早版本
剃刀
var fileversion = '@this.AddFileVersionToPath("/js/components/forms.js")';
扩展方法
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.TagHelpers.Internal;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
public static class IRazorPageExtensions
{
public static string AddFileVersionToPath(this IRazorPage page, string path)
{
var context = page.ViewContext.HttpContext;
IMemoryCache cache = context.RequestServices.GetRequiredService<IMemoryCache>();
var hostingEnvironment = context.RequestServices.GetRequiredService<IHostingEnvironment>();
var versionProvider = new FileVersionProvider(hostingEnvironment.WebRootFileProvider, cache, context.Request.Path);
return versionProvider.AddFileVersionToPath(path);
}
}