Chasing a report that Edge still hides the whole map bar when "Hide Filters" is clicked, after that layout was fixed. Edge is Chromium, so a rendering difference against Chrome was already suspicious. It is not a rendering difference.
What the server tells browsers
index.html, every SPA route serving it, style.css, themes.css and every generated entry bundle (app.js, aprs.js, map-core.js, …) go through one response builder that sends:
None of those URLs change when the bytes behind them do — only esbuild's shared chunks are content-addressed (chunk-<hash>.js), entry names are fixed. The ETag is build-stamped, but immutable says don't ask, and a year of max-age says the same thing to anything that ignores it.
So a browser that loaded the app once can go on serving that copy of the page, stylesheet and bundles indefinitely. A fix ships; the browser that happened to cache the old stylesheet keeps rendering the old behaviour; the browser that got hard-reloaded shows the fix. Which is exactly the shape of the report.
Fix
Asset
Policy
chunk-<hash>.js
immutable, 1 year — the name changes with the bytes
/vendor/opus-decoder-0.7.11.min.js
immutable — version is in the URL
index.html and all its routes, style.css, themes.css, entry bundles, bandplan.json, /vendor/leaflet.js
no-cache — ask, and get a 304
no-cache is not "do not cache": the copy is kept and revalidated, so the usual answer is a 304 with no body. Cost is one conditional request per asset per load.
Verification
Unit tests on the policy each asset gets, including that a real hashed chunk from the manifest is still immutable.
Endpoint tests through the actix app: the page, the stylesheet and app.js come back with no-cache and an ETag, and an unchanged style.css answers 304 under the same policy.
cargo test -p trx-frontend-http 59 passed; fmt and clippy clean.
About the Edge symptom
This is the most likely reason it survived the layout fix, but I could not confirm it here — there is no Edge on this machine, and the map bar renders correctly in Chromium in both states. A hard reload in Edge (Ctrl+Shift+R) will settle it in five seconds: if the bar behaves after that, it was the cache and this change stops it recurring. If it still hides the whole bar, it is a genuine layout problem and I will want the Edge version — the collapsed state leans on width: fit-content with both left and right anchored, which is exactly the kind of over-constrained absolute box where engines have historically differed, and I would rewrite it to something unambiguous rather than guess again.
Chasing a report that Edge *still* hides the whole map bar when "Hide Filters" is clicked, after that layout was fixed. Edge is Chromium, so a rendering difference against Chrome was already suspicious. It is not a rendering difference.
## What the server tells browsers
`index.html`, every SPA route serving it, `style.css`, `themes.css` and every generated entry bundle (`app.js`, `aprs.js`, `map-core.js`, …) go through one response builder that sends:
```
Cache-Control: public, max-age=31536000, immutable
```
None of those URLs change when the bytes behind them do — only esbuild's shared chunks are content-addressed (`chunk-<hash>.js`), entry names are fixed. The ETag is build-stamped, but `immutable` says don't ask, and a year of `max-age` says the same thing to anything that ignores it.
So a browser that loaded the app once can go on serving that copy of the page, stylesheet and bundles indefinitely. A fix ships; the browser that happened to cache the old stylesheet keeps rendering the old behaviour; the browser that got hard-reloaded shows the fix. Which is exactly the shape of the report.
## Fix
| Asset | Policy |
|---|---|
| `chunk-<hash>.js` | `immutable`, 1 year — the name changes with the bytes |
| `/vendor/opus-decoder-0.7.11.min.js` | `immutable` — version is in the URL |
| index.html and all its routes, `style.css`, `themes.css`, entry bundles, `bandplan.json`, `/vendor/leaflet.js` | `no-cache` — ask, and get a 304 |
`no-cache` is not "do not cache": the copy is kept and revalidated, so the usual answer is a 304 with no body. Cost is one conditional request per asset per load.
## Verification
- Unit tests on the policy each asset gets, including that a real hashed chunk from the manifest is still immutable.
- Endpoint tests through the actix app: the page, the stylesheet and `app.js` come back with `no-cache` and an ETag, and an unchanged `style.css` answers 304 under the same policy.
- `cargo test -p trx-frontend-http` 59 passed; fmt and clippy clean.
## About the Edge symptom
This is the most likely reason it survived the layout fix, but I could not confirm it here — there is no Edge on this machine, and the map bar renders correctly in Chromium in both states. **A hard reload in Edge (Ctrl+Shift+R) will settle it in five seconds:** if the bar behaves after that, it was the cache and this change stops it recurring. If it still hides the whole bar, it is a genuine layout problem and I will want the Edge version — the collapsed state leans on `width: fit-content` with both `left` and `right` anchored, which is exactly the kind of over-constrained absolute box where engines have historically differed, and I would rewrite it to something unambiguous rather than guess again.
index.html, the stylesheets and the entry bundles are all served from fixed
URLs and answered with `public, max-age=31536000, immutable`. Nothing in
those URLs changes when the bytes behind them do, and immutable tells the
browser not to ask, so a client that visited once could go on running the
page it downloaded then — for a year, with the build-stamped ETag never
consulted. That is how a layout fix ships and one browser still shows the
old behaviour while every other one has it: not a rendering difference, a
copy of last week's stylesheet.
Only the shared chunks are content-addressed — esbuild hashes their names —
so only they can be kept forever. Everything served from a stable URL now
answers `no-cache`, which asks and gets a 304 in the ordinary case, at the
cost of one conditional request per asset per load. Vendored files with a
version in the URL stay immutable; Leaflet, whose URL does not name its
version, revalidates with the rest.
Covered both ways: a unit test on the policy each asset gets, and endpoint
tests that the page, the stylesheet and app.js come back revalidating with an
ETag, and that an unchanged one answers 304 under the same policy.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SyX26FCpMQxiBoC7r5K1A7
Signed-off-by: Stan Grams <sjg@haxx.space>
sjg
merged commit c8b6f2d536 into main2026-08-07 19:02:46 +02:00
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Chasing a report that Edge still hides the whole map bar when "Hide Filters" is clicked, after that layout was fixed. Edge is Chromium, so a rendering difference against Chrome was already suspicious. It is not a rendering difference.
What the server tells browsers
index.html, every SPA route serving it,style.css,themes.cssand every generated entry bundle (app.js,aprs.js,map-core.js, …) go through one response builder that sends:None of those URLs change when the bytes behind them do — only esbuild's shared chunks are content-addressed (
chunk-<hash>.js), entry names are fixed. The ETag is build-stamped, butimmutablesays don't ask, and a year ofmax-agesays the same thing to anything that ignores it.So a browser that loaded the app once can go on serving that copy of the page, stylesheet and bundles indefinitely. A fix ships; the browser that happened to cache the old stylesheet keeps rendering the old behaviour; the browser that got hard-reloaded shows the fix. Which is exactly the shape of the report.
Fix
chunk-<hash>.jsimmutable, 1 year — the name changes with the bytes/vendor/opus-decoder-0.7.11.min.jsimmutable— version is in the URLstyle.css,themes.css, entry bundles,bandplan.json,/vendor/leaflet.jsno-cache— ask, and get a 304no-cacheis not "do not cache": the copy is kept and revalidated, so the usual answer is a 304 with no body. Cost is one conditional request per asset per load.Verification
app.jscome back withno-cacheand an ETag, and an unchangedstyle.cssanswers 304 under the same policy.cargo test -p trx-frontend-http59 passed; fmt and clippy clean.About the Edge symptom
This is the most likely reason it survived the layout fix, but I could not confirm it here — there is no Edge on this machine, and the map bar renders correctly in Chromium in both states. A hard reload in Edge (Ctrl+Shift+R) will settle it in five seconds: if the bar behaves after that, it was the cache and this change stops it recurring. If it still hides the whole bar, it is a genuine layout problem and I will want the Edge version — the collapsed state leans on
width: fit-contentwith bothleftandrightanchored, which is exactly the kind of over-constrained absolute box where engines have historically differed, and I would rewrite it to something unambiguous rather than guess again.