【问题标题】:How to cache static files in ASP.NET Core?如何在 ASP.NET Core 中缓存静态文件?
【发布时间】:2023-06-26 09:36:02
【问题描述】:

我似乎无法在 ASP.NET Core 2.2 中启用静态文件缓存。我的Configure 中有以下内容:

public void Configure(IApplicationBuilder app, IHostingEnvironment env) {
  if (env.IsDevelopment()) {
    app.UseDeveloperExceptionPage();
    app.UseCors(...);
  }
  else {
    app.UseHsts();
  }

  app.UseHttpsRedirection();
  app.UseAuthentication();
  app.UseSignalR(routes => { routes.MapHub<NotifyHub>("/..."); });

  app.UseResponseCompression();
  app.UseStaticFiles();
  app.UseSpaStaticFiles(new StaticFileOptions() {
    OnPrepareResponse = (ctx) => {
      ctx.Context.Response.Headers[HeaderNames.CacheControl] = "public, max-age=31557600"; // cache for 1 year
    }
  });
  app.UseMvc();

  app.UseSpa(spa => {
    spa.Options.SourcePath = "ClientApp";
    if (env.IsDevelopment()) {
      spa.UseVueCli(npmScript: "serve", port: 8080);
    }
  });
}

当我尝试使用 chrome 在 HTTPS 上审核生产站点时,我不断收到“使用有效的缓存策略提供静态资产”:

在网络选项卡中,标题中没有提到缓存,当我按 F5 时,似乎所有内容都来自磁盘缓存。但是,如果审核显示无效,我如何确定我的缓存设置有效?

【问题讨论】:

    标签: vue.js asp.net-core caching static-files


    【解决方案1】:

    我不知道 UseSpaStaticFiles 是什么,但您可以在 UseStaticFiles 中添加缓存选项。您错过了设置 Expires 标头。

    // Use static files
    app.UseStaticFiles(new StaticFileOptions {
        OnPrepareResponse = ctx =>
        {
            // Cache static files for 30 days
            ctx.Context.Response.Headers.Append("Cache-Control", "public,max-age=2592000");
            ctx.Context.Response.Headers.Append("Expires", DateTime.UtcNow.AddDays(30).ToString("R", CultureInfo.InvariantCulture));
        }
    });
    

    请注意,当您对静态文件进行更改时,您还需要一种使缓存无效的方法。

    我已经写了一篇关于此的博客文章:Minify and cache static files in ASP.NET Core

    【讨论】:

    • 你好 FS。题;对于缓存失效,你为什么决定不使用 MVC 'asp-append-version' 标签。 IE。 -->
    • 你好,我想尽量使用纯HTML和纯JavaScript。
    【解决方案2】:

    这适用于 ASP.NET Core 2.2 到 3.1:

    我知道这有点类似于 Fredrik 的回答,但您不必输入文字字符串来获取缓存控制标头

    app.UseStaticFiles(new StaticFileOptions()
    {
        HttpsCompression = Microsoft.AspNetCore.Http.Features.HttpsCompressionMode.Compress,               
        OnPrepareResponse = (context) =>
        {
            var headers = context.Context.Response.GetTypedHeaders();
            headers.CacheControl = new Microsoft.Net.Http.Headers.CacheControlHeaderValue
            {
                Public = true,
                MaxAge = TimeSpan.FromDays(30)
            };
        }
    });
    

    【讨论】:

    • 您缺少 Expires 标头。
    • @Ali 如果响应包含Expires 标头和max-age 指令,则max-age 优先。参考:13.2.4 到期计算 - w3.org/Protocols/rfc2616/rfc2616-sec13.html max-age 指令优先于 Expires,因此如果响应中存在 max-age,则计算很简单:
    • 注意:不需要设置HttpsCompressionMode!