【问题标题】:ASP.NET MVC Bundling cache. (Detecting css files changes) (internal behaviour)ASP.NET MVC 捆绑缓存。 (检测 css 文件更改)(内部行为)
【发布时间】:2013-08-29 13:53:03
【问题描述】:

我一直在深入研究 ASP.NET MVC 内部功能(不同的原因),但仍然无法涵盖所有​​行为。其中一个我没有是 subj。

它的工作方式如下:

如果我捆绑了一些文件(例如 css 文件),框架会检测到这些更改为新捆绑包生成新的 id(让浏览器更容易刷新更改),例如 href="/Content/css?v=qartPE4jGe-l1U0I7kNDZPZzVTdh0kT8VBZZA_uURjI1"。

我真正想了解的内容:

  1. 框架(可能不是 MVC 而是 .NET 的东西)检测到文件已更改(因为 没有活动的目录观察程序(如即使网络服务器离线,我也可以更改文件)以实时查看文件更改,并且系统实际上检测到文件内容更改(我尝试只是重新保存文件而不更改其内容和捆绑包号也没有改变))? (我认为显然系统无法比较每个文件内容来检测每个请求的变化)。

  2. 框架在哪里(以及如何)存储当前包 id 以及它如何存储以前的版本(因为以前的包在转到其 url 时仍然可用) ?

非常感谢!

【问题讨论】:

  • 该站点提供了对捆绑机制的一些见解:dotnetexpertguide.com/2012/10/… 至于您的第二个问题,默认情况下似乎使用了服务器缓存。捆绑包 ID 是文件内容的散列,因此会在您更改内容时更改。旧版本不存储在服务器上,不再可用。该 URL 很可能仍然有效(因为它只是一个查询字符串,用于让浏览器意识到它需要下载新内容),但您将获得新内容,而不是旧内容。

标签: css asp.net-mvc bundle


【解决方案1】:

ASP.NET 优化框架将包响应缓存在HttpContext.Cache 中,并使用CacheDependency 来监视包中的每个文件的更改。这就是为什么直接更新文件会使缓存失效并重新生成包的原因。

捆绑文件名是捆绑内容的哈希值,可确保在修改任何捆绑文件时更改 URL。捆绑包的虚拟路径用作缓存键。

库中的相关代码(注意这有点过时,但我相信逻辑还是一样的):

internal BundleResponse GetBundleResponse(BundleContext context)
{
    // check to see if the bundle response is in the cache
    BundleResponse bundleResponse = Bundle.CacheLookup(context);
    if (bundleResponse == null || context.EnableInstrumentation)
    {
        // if not, generate the bundle response and cache it
        bundleResponse = this.GenerateBundleResponse(context);
        if (context.UseServerCache)
        {
            this.UpdateCache(context, bundleResponse);
        }
    }
    return bundleResponse;
}

private void UpdateCache(BundleContext context, BundleResponse response)
{
    if (context.UseServerCache)
    {
        // create a list of all the file paths in the bundle
            List<string> list = new List<string>();
        list.AddRange(
            from f in response.Files
            select f.FullName);
        list.AddRange(context.CacheDependencyDirectories);
        string cacheKey = Bundle.GetCacheKey(context.BundleVirtualPath);
        // insert the response into the cache with a cache dependency that monitors
        // the bundle files for changes
        context.HttpContext.Cache.Insert(cacheKey, response, new CacheDependency(list.ToArray()));
        context.HttpContext.Response.AddCacheItemDependency(cacheKey);
        this._cacheKeys.Add(cacheKey);
    }
}

最后,对于旧的捆绑 URL 工作,我想您会发现它们要么从浏览器缓存中返回,要么实际上返回捆绑的最新版本,因为捆绑路径没有改变,只有版本查询字符串。

【讨论】:

  • 感谢您的回答。但是,我不确定我是否看到问题的两个部分中的任何一个的确切答案。 1.它是如何检测相关文件变化的? 2. 缓存实际在哪里(或如何)存储值? (如果存在多个捆绑包(旧捆绑包和新捆绑包)。
  • 我已经更新了我的答案,但简而言之,CacheDependency 对象监视文件的更改,并且使用捆绑虚拟路径作为键缓存捆绑响应(每个捆绑只有一个条目是存储因此更新捆绑文件会删除现有条目)。
  • 是的,但核心问题是它究竟如何监控文件的更改?是否存在任何系统观察程序(我对此表示怀疑,因为应用程序未运行且文件已更改时的情况如何)?否则,它如何检查文件修改?每个请求?
  • 嗯,谢谢你的回答,但对我来说仍然听起来像:“它只是使用缓存”。好吧,我确信它使用缓存(这是网络(和许多其他)技术的工作方式),但我的问题的重点是实用的(不仅仅是一些理论,捆绑使用哪些类或模块):这是为了了解是否页面渲染是否会检查每个 Web 请求的文件更改(来自捆绑文件)?或不?如果不是,那么(奇怪地/理论上)它监控这些变化的确切方式是什么?
  • 我已经为您的问题提供了答案。如果您想了解CacheDependency 的内部结构以及它究竟如何 监控文件,那么我建议您发布一个不同的问题。我建议您在得出“它只是使用缓存”的结论之前正确阅读我的答案。
猜你喜欢
  • 1970-01-01
  • 2021-07-23
  • 1970-01-01
  • 2013-01-06
  • 2014-09-25
  • 1970-01-01
  • 2020-06-07
  • 2013-01-21
  • 1970-01-01
相关资源
最近更新 更多