Cache-bust style.css so a deploy doesn't leave visitors on a stale copy
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 19s
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 19s
Browsers apply much more aggressive heuristic caching to a linked stylesheet than to the dynamically-rendered HTML that references it, so a CSS-only deploy could silently leave an already-open browser serving the old styles until a hard refresh -- exactly what made today's dashboard polish changes look broken while testing, until forcing a fresh fetch. Appends a content-hash query param computed once at startup. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
8423f01014
commit
c8a9dea993
2 changed files with 21 additions and 1 deletions
|
|
@ -1,5 +1,8 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
from fastapi import APIRouter, Request
|
from fastapi import APIRouter, Request
|
||||||
from fastapi.templating import Jinja2Templates
|
from fastapi.templating import Jinja2Templates
|
||||||
|
|
||||||
|
|
@ -9,6 +12,23 @@ router = APIRouter()
|
||||||
templates = Jinja2Templates(directory="app/web/templates")
|
templates = Jinja2Templates(directory="app/web/templates")
|
||||||
|
|
||||||
|
|
||||||
|
def _asset_version(path: str) -> str:
|
||||||
|
"""A short hash of a static asset's content, used to cache-bust it in
|
||||||
|
templates -- browsers apply much more aggressive heuristic caching to
|
||||||
|
linked CSS/JS than to the dynamically-rendered HTML that references it,
|
||||||
|
so without this, a deploy that only changes style.css can leave a
|
||||||
|
visitor's browser silently serving the old stylesheet until they
|
||||||
|
hard-refresh. Computed once at startup since the file is baked into the
|
||||||
|
image and won't change while this process is running."""
|
||||||
|
try:
|
||||||
|
return hashlib.md5(Path(path).read_bytes()).hexdigest()[:8]
|
||||||
|
except FileNotFoundError:
|
||||||
|
return "0"
|
||||||
|
|
||||||
|
|
||||||
|
templates.env.globals["static_version"] = _asset_version("app/static/css/style.css")
|
||||||
|
|
||||||
|
|
||||||
@router.get("/")
|
@router.get("/")
|
||||||
def dashboard(request: Request):
|
def dashboard(request: Request):
|
||||||
return templates.TemplateResponse(request, "dashboard.html", {})
|
return templates.TemplateResponse(request, "dashboard.html", {})
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Power Compare</title>
|
<title>Power Compare</title>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4"></script>
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@4"></script>
|
||||||
<link rel="stylesheet" href="/static/css/style.css">
|
<link rel="stylesheet" href="/static/css/style.css?v={{ static_version }}">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<nav class="topnav">
|
<nav class="topnav">
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue