Cache-busting so deploys are visible immediately
deploy / deploy (push) Successful in 26s

The site sits behind a CDN and shipped static assets with no Cache-Control
and no versioning, so browsers/CDN kept serving stale css/js after a deploy
(the "design didn't change" symptom).

- HTML responses now send Cache-Control: no-cache, no-store, must-revalidate
  so the page itself is always revalidated.
- Static assets get a long cache and are fingerprinted via asp-append-version
  (/css/site.css?v=<contenthash>), so they bust automatically on every change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
soroush.asadi
2026-06-26 11:03:37 +03:30
parent 8896740895
commit ffba74a727
3 changed files with 29 additions and 7 deletions
+2 -2
View File
@@ -9,8 +9,8 @@
@@font-face { font-family:'SpaceMono'; src:url('/fonts/SpaceMono-Regular.woff2') format('woff2'); font-display:swap; } @@font-face { font-family:'SpaceMono'; src:url('/fonts/SpaceMono-Regular.woff2') format('woff2'); font-display:swap; }
</style> </style>
<!-- Tailwind: prebuilt + purged admin stylesheet (`npm run build`). No runtime CDN. --> <!-- Tailwind: prebuilt + purged admin stylesheet (`npm run build`). No runtime CDN. -->
<link rel="stylesheet" href="/css/tailwind-admin.css" /> <link rel="stylesheet" href="/css/tailwind-admin.css" asp-append-version="true" />
<link rel="stylesheet" href="/css/site.css" /> <link rel="stylesheet" href="/css/site.css" asp-append-version="true" />
</head> </head>
<body class="min-h-screen bg-base text-slate-200 antialiased"> <body class="min-h-screen bg-base text-slate-200 antialiased">
<div class="flex min-h-screen"> <div class="flex min-h-screen">
+4 -4
View File
@@ -26,9 +26,9 @@
</style> </style>
<!-- Tailwind: prebuilt + purged stylesheet (`npm run build`). No runtime CDN. --> <!-- Tailwind: prebuilt + purged stylesheet (`npm run build`). No runtime CDN. -->
<link rel="stylesheet" href="/css/tailwind.css" /> <link rel="stylesheet" href="/css/tailwind.css" asp-append-version="true" />
<link rel="stylesheet" href="/css/site.css" /> <link rel="stylesheet" href="/css/site.css" asp-append-version="true" />
<link rel="icon" href="/logo-mark.svg" type="image/svg+xml" /> <link rel="icon" href="/logo-mark.svg" type="image/svg+xml" asp-append-version="true" />
</head> </head>
<body class="site antialiased"> <body class="site antialiased">
@@ -155,7 +155,7 @@
</div> </div>
</footer> </footer>
<script src="/js/app.js" defer></script> <script src="/js/app.js" defer asp-append-version="true"></script>
@await RenderSectionAsync("Scripts", required: false) @await RenderSectionAsync("Scripts", required: false)
</body> </body>
</html> </html>
+23 -1
View File
@@ -50,7 +50,29 @@ using (var scope = app.Services.CreateScope())
} }
app.UseStatusCodePagesWithReExecute("/Error/{0}"); app.UseStatusCodePagesWithReExecute("/Error/{0}");
app.UseStaticFiles();
// HTML pages must never be cached by the browser or CDN, so a new deploy is
// visible immediately. Static assets are fingerprinted via asp-append-version
// (?v=hash), so they can be cached aggressively and bust automatically.
app.Use(async (context, next) =>
{
context.Response.OnStarting(() =>
{
if (context.Response.ContentType?.Contains("text/html", StringComparison.OrdinalIgnoreCase) == true)
{
context.Response.Headers.CacheControl = "no-cache, no-store, must-revalidate";
context.Response.Headers.Pragma = "no-cache";
}
return Task.CompletedTask;
});
await next();
});
app.UseStaticFiles(new StaticFileOptions
{
OnPrepareResponse = ctx =>
ctx.Context.Response.Headers.CacheControl = "public, max-age=31536000"
});
// Serve uploaded files from /data/uploads under /uploads/* // Serve uploaded files from /data/uploads under /uploads/*
var uploadsPath = Path.Combine(dataDir, "uploads"); var uploadsPath = Path.Combine(dataDir, "uploads");