附加一个版本,指示缓存的旧版本的静态文件是最新的,以便不使用

页面创建日期 :

前一段很长,所以如果你只看程序,请跳过它。

环境

Visual Studio
  • Visual Studio 2019
ASP.NET Core
  • 3.1 (Razor 页面, MVC)

关于缓存网页上的文件

访问网页时,除了 HTML 外,.js 文件 (Javascript) 、.css 文件(样式表)和图像文件将下载到客户端以查看和运行。 但是,一些图像文件可能很大,每次下载都会增加成本。 此外,对于 .js 和 .css 文件,同一文件通常也用于其他页面,因此每次下载这些文件都没有任何意义。 这些文件可能会在下载后临时存储在浏览器中。 这就是 所谓的缓存。

例如,如果缓存了文件,则当您访问同一页面时,HTML 会从 Web 服务器下载。 对于其他文件,如果缓存可用,则使用本地存储的文件进行查看和运行,而无需下载。 这会降低服务器负载,并允许客户端快速查看页面,而无需消耗通信带宽。

缓存引起的问题

服务器上的文件和缓存的文件是否相同通常取决于 HTML 中描述的文件路径。 如果文件路径相同,则通常使用缓存的文件。 (可能还有其他条件,但文件路径是确定的)

下面是文件路径的示例。 href 和 src 属性参数适用。

<!-- スタイルシート (.css) -->
<link rel="stylesheet" href="/css/site.css" />

<!-- 画像ファイル -->
<img src="/image/sample.png" alt="サンプル画像" />

<!-- JavaScript (.js) -->
<script src="/js/site.js"></script>

但是,如果发生此行为,这可能是一个问题。

例如,如果用户在首次访问时具有版本 1 的 JavaScript 文件,则缓存版本 1 的 JavaScript 文件。 然后,在服务器端发布版本 2 的 JavaScript 文件。 如果用户访问同一页面时 JavaScript 文件具有相同的路径,则可能会使用缓存的版本 1 Javascript 文件,而不下载服务器版本 2 的 JavaScript 文件。 这可能会导致发布者无意中出现故障。

这一次,在用户的反应之一,"尝试删除缓存",我认为经常看到,因为这可能是原因。

服务器端缓存问题解决方法

如前所述,是否使用缓存的文件在很大程度上取决于文件路径 (URL)。

因此,在更新文件时,可以重命名文件以强制下载新文件。

例如,如果版本 1 文件是

<link rel="stylesheet" href="/css/site.css" />

更新文件的版本 2 是

<link rel="stylesheet" href="/css/site2.css" />

这将在客户端.css使用 site2 文件。

但是,手动执行此操作可能会给更改路径或更改物理文件名造成麻烦和错误。

将查询参数附加到文件路径

Web 的工作方式允许您在路径后面添加键和值组合的查询参数。 即使物理文件相同,如果查询参数不同,客户端缓存机制也会将该文件识别为单独的文件。 查询参数是附加的,如果没有用途,则没有任何意义。

查询参数可以以以下格式附加到路径:

<!-- クエリパラメータなし -->
<link rel="stylesheet" href="/css/site.css" />

<!-- クエリパラメータあり -->
<link rel="stylesheet" href="/css/site.css?key=value" />

此机制要求更改路径,但不需要重命名物理文件。

以编程方式自动添加查询参数(一个坏示例)

通过以编程方式自动附加该查询参数, 即使更改了静态文件,也无需手动更改文件路径。

一个简单的示例是,当用户访问网页时,将当前时间添加到查询参数。 这很容易,因为我认为任何编程语言都可以在一行中编写。 我认为生成示例如下所示。

<link rel="stylesheet" href="/css/site.css?20210223120000" />

但是,这样做的缺点是缓存没有好处。 每次访问网页时,路径都会更改,因此尽管该文件与上次相同 它被视为单独的文件,因此每次从服务器下载 CSS 文件。 旧版本的文件将永远不会使用,但它只是与不使用缓存功能相同。

ASP.NET Core 中的查询参数附加进行文件版本控制

虽然不再有前置 ASP.NET 但核心是解决此缓存问题的标准方法。

您所要的只是将 属性附加到描述 asp-append-version="true" 文件路径的标记,如下所示:

<link rel="stylesheet" href="~/css/site.css" asp-append-version="true"/>
<img src="/image/sample.png" asp-append-version="true"/>
<script src="~/js/site.js" asp-append-version="true"></script>

发布到 Web 后,当您实际访问页面时,将按如下方式展开它:

<link rel="stylesheet" href="/css/site.css?v=S2ihmzMFFc3FWmBWsR-NiddZWa8kbyaQYBx2FDkIoHs" />
<img src="/image/sample.png?v=Z0tUqQmLt_3L_NSzPmkbZKxL8cMxglf08BwWb5Od5z4" />
<script src="/js/site.js?v=dLGP40S79Xnx6GqUthRF6NWvjvhQ1nOvdVSwaNcgG18"></script>

随机字符串被添加,但每次访问时都不会更改。 此字符串是哈希值,根据引用文件的内容生成。 因此,只要文件的内容保持不变,它们将生成相同的字符串。 如果文件的内容发生更改,则更改为新字符串。

因此,如果文件相同,则路径相同,因此缓存的文件将优先使用。 如果文件已更新,路径将发生更改,因此将下载并使用新文件。

顺便说一 asp-append-version="true" 下,此属性通常仅包含放置在 wwwroot 文件夹中的静态文件。 请注意,随机字符串不会展开,即使设置为其他文件。

关于示例程序

默认项目模板.js site asp-append-version 模板。 site.css 没有 asp-append-version 附加 。

示例程序 _Layout.cshtml 将 site.js、站点.css asp-append-version 文件添加到每个站点。 我们还添加 img 标记作为参考,并将其添加到 asp-append-version 中。