Skip to content

fix: guarantee unique cache-buster per deploy#96

Merged
antosubash merged 1 commit intomainfrom
fix/cache-buster-defaults
Apr 8, 2026
Merged

fix: guarantee unique cache-buster per deploy#96
antosubash merged 1 commit intomainfrom
fix/cache-buster-defaults

Conversation

@antosubash
Copy link
Copy Markdown
Owner

Summary

Two gaps were letting browsers cache stale JS/CSS across deploys, causing the exact symptoms from #94's original bug report to reappear after that PR shipped:

  • Dockerfile hardcoded ARG DEPLOY_VERSION=latest, so every image set DEPLOYMENT_VERSION=latest and every asset URL ended in ?v=latest. InertiaMiddleware.GetVersion()'s assembly-timestamp fallback was masked, the X-Inertia-Version header never changed between deploys, and browsers kept serving cached bundles that referenced chunk hashes no longer on disk — hard 404 on dynamic imports like Home-MQTOkMvb.mjs.
  • The importmap in index.html referenced five vendor entries (/js/vendor/react.js, react-dom, react-dom/client, react/jsx-runtime, @inertiajs/react) with no ?v= suffix at all, so fresh deploys kept using the browser's cached vendor chunks indefinitely.

Changes

  • Dockerfile: default DEPLOY_VERSION to empty. When unset, InertiaMiddleware.GetVersion() derives the version from the entry assembly's last-write timestamp (yyyyMMddHHmmss), which advances on every publish. Pass --build-arg DEPLOY_VERSION=$(git rev-parse --short HEAD) for deterministic versions if needed.
  • template/SimpleModule.Host/wwwroot/index.html: add ?v=<!--DEPLOY_VERSION--> to each importmap entry so they participate in the same replacement pass as app.js and app.css.

Test plan

Verified locally with dotnet run --project template/SimpleModule.Host:

Asset Cache buster
<meta name="cache-buster"> 20260408111445
/css/app.css ?v=20260408111445
/_content/SimpleModule.PageBuilder/simplemodule.pagebuilder.css ?v=20260408111445
/js/vendor/react.js (+ 4 other vendor entries) ?v=20260408111445
/js/app.js ?v=20260408111445

Direct fetches all returned 200 with correct Content-Type:

  • /css/app.csstext/css
  • /_content/SimpleModule.PageBuilder/simplemodule.pagebuilder.csstext/css
  • /js/app.jstext/javascript
  • /js/vendor/react.jstext/javascript
  • /_content/SimpleModule.Users/SimpleModule.Users.pages.jstext/javascript

Also verified via docker build -t simplemodule:test . && docker run ... that the rendered HTML emits a fresh timestamp instead of the literal latest string.

  • Rebuild and deploy the image; confirm no stale-asset errors in production browser console after full refresh.
  • Confirm subsequent deploys continue to get unique ?v= values (no manual --build-arg needed).

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented Apr 8, 2026

Deploying simplemodule-website with  Cloudflare Pages  Cloudflare Pages

Latest commit: 6e348ea
Status: ✅  Deploy successful!
Preview URL: https://b067adb7.simplemodule-website.pages.dev
Branch Preview URL: https://fix-cache-buster-defaults.simplemodule-website.pages.dev

View logs

The Dockerfile hardcoded `ARG DEPLOY_VERSION=latest`, so every image
shipped with `DEPLOYMENT_VERSION=latest` and every asset URL ended
in `?v=latest`. InertiaMiddleware.GetVersion()'s assembly-timestamp
fallback was masked, the X-Inertia-Version header never changed
between deploys, and browsers kept serving cached bundles that
referenced chunk hashes no longer on disk — hard 404 on dynamic
imports like Home-MQTOkMvb.mjs.

Fix: default DEPLOY_VERSION to empty. When unset, GetVersion()
derives the version from the entry assembly's last-write timestamp
(yyyyMMddHHmmss), which advances on every publish and guarantees
cache invalidation with zero configuration. Override with
`--build-arg DEPLOY_VERSION=$(git rev-parse --short HEAD)` for
deterministic versions if needed.

Vendor chunks (/js/vendor/*.js) are intentionally left uncached —
they only change when the underlying npm packages change, not per
deploy, so a cache buster on them would just force a re-download
of ~130 KB of identical bytes every release.
@antosubash antosubash force-pushed the fix/cache-buster-defaults branch from bd3dac6 to 6e348ea Compare April 8, 2026 11:41
@antosubash antosubash enabled auto-merge (squash) April 8, 2026 11:42
@antosubash antosubash merged commit 3b14835 into main Apr 8, 2026
5 checks passed
@antosubash antosubash deleted the fix/cache-buster-defaults branch April 8, 2026 11:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant