fix: avoid caching personalized pages#434
Conversation
Co-authored-by: theg1239 <theg1239@users.noreply.github.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryThis PR fixes a service-worker bug where personalized HTML pages (
Confidence Score: 4/5Safe to merge — the fix is targeted and the logic is straightforward, with no changes outside the service worker file. The exact-path set and the isCacheableResponse helper are correct and well-scoped. The one functional note worth a second look is that no-cache is treated the same as no-store/private, which is more conservative than the HTTP spec requires; this is safe but may silently bypass the stale-while-revalidate benefit for non-personalized routes that use no-cache for revalidation. The version bump and eviction logic are correct. Only public/sw.js changed — no other files need attention. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[fetch event / PREFETCH_ROUTES] --> B{isUncacheable?}
B -- yes --> C[Skip — browser handles natively]
B -- no --> D[Fetch from network]
D --> E{isCacheableResponse?}
E -- ok + not opaque --> F{Cache-Control header}
F -- no-store / no-cache / private --> G[Do NOT cache]
F -- absent or cacheable --> H[Write to STATIC / PAGE / RUNTIME cache]
E -- not ok or opaque --> G
Reviews (1): Last reviewed commit: "fix: avoid caching personalized pages" | Re-trigger Greptile |
| @@ -1,4 +1,4 @@ | |||
| const CACHE_VERSION = "v3"; | |||
| const CACHE_VERSION = "v4"; | |||
There was a problem hiding this comment.
Commit message could be more descriptive
The message fix: avoid caching personalized pages follows conventional-commit form but is thin — it doesn't mention that /auth exact-match was missing from the no-cache set, that Cache-Control: private/no-store/no-cache is now inspected before every cache write, or that the version bump was needed to evict stale entries. A reader scanning git log won't understand the root cause or the scope of the fix without opening the PR. Something like fix(sw): add /auth+/ exact-no-cache paths, honour Cache-Control private/no-store, bump cache to v4 captures all three changes in one line.
Context Used: Encourage people to write better commit messages (source)
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| function isCacheableResponse(response) { | ||
| if (!response || !response.ok || response.type === "opaque") return false; | ||
|
|
||
| const cacheControl = response.headers.get("cache-control") || ""; | ||
| return !/(^|,\s*)(no-store|no-cache|private)(\s|,|=|$)/i.test(cacheControl); | ||
| } |
There was a problem hiding this comment.
no-cache treated as uncacheable — more conservative than HTTP requires
Per RFC 9111, Cache-Control: no-cache means "validate before serving from cache," not "never cache." Treating it as uncacheable here prevents the SW from ever storing or serving such responses, which is safe but more aggressive than necessary. It means any response annotated no-cache (e.g. a public asset served with short-lived revalidation) will always hit the network, bypassing the stale-while-revalidate benefit entirely. Consider whether this is intentional before this becomes a performance concern for non-personalized routes.
Summary
/and exact/authHTML.Cache-Control: private,no-store, andno-cachebefore writing responses into SW caches.Bug and impact
A recent service-worker change cached navigation HTML without considering cookies or cache-control headers. This allowed stale signed-out
/authHTML to be served to signed-in users, and stale personalized home HTML (for example, another user's welcome text) to be served from native/PWA page cache on shared installs.Root cause
/authdid not match the existing/auth/no-cache prefix,/was preloaded into the page cache, and cache writes ignored response cache-control metadata.Validation
node --check public/sw.js/,/auth,/auth/callback, and/modare uncacheable; private/no-store responses are rejected; native prefetch caches/past_papersbut skips/and/auth.DATABASE_URL=postgresql://examcooker:examcooker@localhost:5432/examcooker AUTH_SECRET=dev-secret NEXTAUTH_SECRET=dev-secret AUTH_GOOGLE_ID=placeholder AUTH_GOOGLE_SECRET=placeholder NEXTAUTH_URL=http://localhost:3000 NEXT_PUBLIC_BASE_URL=http://localhost:3000 pnpm build