Fix stale block page preview by cache-busting static assets
The preview iframe stayed blank after a redeploy because /static/js/app.js is served with a 24h Cache-Control and no versioning, so browsers kept using the pre-existing cached copy that predated the preview code. Static CSS/JS references now carry a ?v=<build commit> query string so a new build is never masked by a stale cache. Also makes the CSP's frame-src explicit for the preview iframe rather than relying on the default-src fallback. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01TTKpGMQzpfDsvedu1hvSUf
This commit is contained in:
@@ -30,12 +30,24 @@ type PageData struct {
|
||||
Flashes []Flash
|
||||
Alerts []Alert
|
||||
Version string
|
||||
Asset string // cache-busting suffix for /static URLs; changes every build
|
||||
Now time.Time
|
||||
Data any
|
||||
Query url.Values
|
||||
BasePath string
|
||||
}
|
||||
|
||||
// assetVersion busts the browser cache for /static assets on every new
|
||||
// build, so a redeploy is never masked by a day-old cached app.js. It falls
|
||||
// back to the semantic version when no VCS commit was embedded (e.g. a build
|
||||
// outside a git checkout), which is still stable within one running process.
|
||||
var assetVersion = func() string {
|
||||
if version.Commit != "" {
|
||||
return version.Commit
|
||||
}
|
||||
return version.Version
|
||||
}()
|
||||
|
||||
// Alert is a persistent banner such as "a restart is required".
|
||||
type Alert struct {
|
||||
Level string // warning, danger, info
|
||||
@@ -94,6 +106,7 @@ func (s *Server) render(w http.ResponseWriter, r *http.Request, page string, dat
|
||||
}
|
||||
|
||||
data.Version = version.Version
|
||||
data.Asset = assetVersion
|
||||
data.Now = time.Now()
|
||||
if data.Query == nil {
|
||||
data.Query = r.URL.Query()
|
||||
@@ -126,6 +139,7 @@ func (s *Server) renderError(w http.ResponseWriter, r *http.Request, status int,
|
||||
data := PageData{
|
||||
Title: http.StatusText(status),
|
||||
Version: version.Version,
|
||||
Asset: assetVersion,
|
||||
Now: time.Now(),
|
||||
Data: map[string]any{
|
||||
"Status": status,
|
||||
|
||||
@@ -418,6 +418,7 @@ func (s *Server) withSecurityHeaders(next http.Handler) http.Handler {
|
||||
"font-src 'self'; "+
|
||||
"connect-src 'self'; "+
|
||||
"form-action 'self'; "+
|
||||
"frame-src 'self'; "+
|
||||
"frame-ancestors 'none'; "+
|
||||
"base-uri 'none'; "+
|
||||
"object-src 'none'")
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<link rel="icon" href="/static/img/favicon.svg" type="image/svg+xml">
|
||||
<link rel="stylesheet" href="/static/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="/static/css/bootstrap-icons.min.css">
|
||||
<link rel="stylesheet" href="/static/css/app.css">
|
||||
<link rel="stylesheet" href="/static/css/app.css?v={{.Asset}}">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -119,7 +119,7 @@
|
||||
</div>
|
||||
|
||||
<script src="/static/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="/static/js/app.js"></script>
|
||||
<script src="/static/js/app.js?v={{.Asset}}"></script>
|
||||
{{block "scripts" .}}{{end}}
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user