1- // Recovers from a rolling deploy rotating the content-hashed /build assets out from
1+ // Recovers from a rolling deploy rotating the content-hashed /assets files out from
22// under a page. Each image serves only its own build and hard-404s unknown hashes, so
33// a client can request a hash the serving replica doesn't have and get missing styles
4- // or a failed asset load. On such a /build load failure we do a bounded full document
4+ // or a failed asset load. On such an asset load failure we do a bounded full document
55// reload: the fresh document (and, under sticky routing, all of its assets) lands on a
66// single live build, so the asset resolves. Bounded via sessionStorage so it can never
77// loop; when the budget is spent it stops rather than reloading forever.
@@ -39,7 +39,7 @@ export function staleAssetRecoveryScript() {
3939 }
4040
4141 function recover ( ) {
42- // One recovery per page: a broken load fails several /build assets at once and each
42+ // One recovery per page: a broken load fails several hashed assets at once and each
4343 // fires its own error event before location.reload() commits — without this guard a
4444 // single incident would burn the entire reload budget.
4545 if ( recovering ) return ;
@@ -62,7 +62,9 @@ export function staleAssetRecoveryScript() {
6262 : el . tagName === "SCRIPT"
6363 ? ( el as HTMLScriptElement ) . src
6464 : null ;
65- if ( url && url . indexOf ( "/build/" ) !== - 1 ) recover ( ) ;
65+ // Match the pathname, not the full URL — a query string or third-party
66+ // URL containing /assets/ must not burn the reload budget.
67+ if ( url && new URL ( url , location . href ) . pathname . indexOf ( "/assets/" ) !== - 1 ) recover ( ) ;
6668 } ,
6769 true
6870 ) ;
0 commit comments