Repository navigation
Conversation
…hell When a hashed bundle under /assets/ is missing (deploy replaced dist/, container restarted on a different build), the request fell through koa-static-cache to the SSR catch-all and got the 200 HTML shell under the .js URL. URL-keyed CDN caches stored that HTML against the asset URL - with the long max-age the deployed shell carried - and page loads then broke on script-parse errors until the cache entries expired (up to 8 days). A guard middleware registered right after the static mounts now answers 404 + Cache-Control: no-store for any request under one of the statically served prefixes (/assets, /images, /javascripts, /favicons) that the mounts did not serve. /static and /.well-known are mounted later and ship with the app, so they are untouched; the dev-mode /assets proxy never falls through, so development behavior is unchanged.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
During today's kernel-patch reboot of the production condenser, requests for hashed bundles under
/assets/fell through thekoa-static-cachemount to the SSR catch-all, which rendered the 200 HTML shell under the.jsURL. CDN caches that key by URL pattern stored that HTML against the asset URL (the deployed build's shell carriedCache-Control: private, max-age=691200; master since carriesprivate, no-store), and page loads then broke with a script-parse error until those entries expire - up to 8 days.Observed live on 2026-11-04 (HKG edge):
Fix
A guard middleware registered right after the static mounts. Any request that reaches it under one of the statically served prefixes (
/assets,/images,/javascripts,/favicons) was not served by those mounts, i.e. the file is missing - it now gets404+Cache-Control: no-storeso neither the CDN nor the browser pins the failure.Scope notes:
/staticand/.well-knownare mounted later in the chain and their contents ship with the app; guarding them from the top would 404 files that exist./assetswebpack proxy never falls through, so development behavior is unchanged.public, max-age=86400000headers) is untouched.private, no-storefor most pages, but the 200-for-a-.js-URL behavior itself remains wrong and is still cacheable under aggressive CDN configs (cache-by-URL-pattern / TTL overrides).Ops note (deploy)
Redeploying this does not clear the already-poisoned CDN entries; a purge of the affected
/assets/*URLs is still required once, right after rollout.Test Plan
jest src/server/__tests__- 17 passed (newstaticAssetPath.test.js+ existingredirect.test.js)server.jscarries 43 pre-existing lint errors on master; this PR adds no new class of error (the guard uses the samefunction*(next)formatting as the sibling middleware, which is what prettier/lint-staged enforces).