Split The code is public; the app answers only to the crew.
Every refresh re-sends the whole first paint: no ETag on `/`, so `no-cache` means re-download instead of 304 #219
Sign in to join this conversation.
Split The code is public; the app answers only to the crew.
Give the first paint an entity tag so a revalidation costs a 304 and a few hundred bytes instead of the whole page.
Measured against
mainat6cb6517, booted locally:private, no-cacheis right - #126 put it there, and the page carries a name, a guest label and a session cookie, so no shared cache may keep it. Butno-cachedoes not mean do not store, it means revalidate before reuse, and a revalidation with nothing to validate against is a full 200 every time: 6.8 KB of gzip on every refresh, every alt-tab back, every phone waking up, when the page has not changed. The server already answers in 1.6-7 ms, so this is bytes on a phone's connection rather than server time - which is exactly the kind of thing the README claims the app cares about.encoded(src/server.ts:54) is the single place a body is chosen and is where the tag belongs: it already knows the bytes it is about to send and whether it gzipped them.Done looks like
GET /carries a strongetagderived from the bytes actually sent (Bun.hashover the identity bytes is enough - name it, do not reach for a crypto hash). Two visits that render the same page produce the same tag; a different player name, a different guest label or a different commit stamp produces a different one.if-none-matchgets304with no body, and with the samecache-control,vary,etagand security headers the 200 carries.content-lengthis absent or0, never the 200's length.vary: accept-encodingstays.304: a first visit must setset-cookie, so the tag check comes after that decision, not before. A test asserts a cookieless request with anyif-none-matchstill gets 200 plusset-cookie.HEAD /is unchanged: headers of the 200, no body, asencodedalready does.if-none-match: *and a malformed or multi-valued header are handled at the boundary rather than trusted - a list is a list, andW/prefixes compare weakly.max-agewithimmutableis never revalidated, so it needs nothing.src/server.test.ts: 200 carries an etag; that etag echoed back gives 304; a changed page gives a different etag and a 200; gzip and identity tags differ; the cookie case above.bun run checkgreen. Quote the before/after byte count of a refresh in the pull.Files I expect to change
src/server.ts,src/server.test.ts.README.md- one line where it describes the first paint's caching.Risks
varyor the security headers is a cache-poisoning shape; the floor belongs on every response, 304 included.encodedand do not hash twice for the two encodings.cache-control: the page is per-visitor, and a shared cache holding it is the fault #126 fixed.Crew
scout - the server's boundary and the tests that hold it.