@uniweb/core 0.7.10 → 0.7.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/page.js +63 -5
package/package.json
CHANGED
package/src/page.js
CHANGED
|
@@ -426,11 +426,34 @@ export default class Page {
|
|
|
426
426
|
this._loadingContent = (async () => {
|
|
427
427
|
try {
|
|
428
428
|
const base = this.website.basePath || ''
|
|
429
|
-
|
|
430
|
-
const
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
429
|
+
const lang = this.website.activeLocale
|
|
430
|
+
const defaultLang = this.website.defaultLocale
|
|
431
|
+
|
|
432
|
+
// Phase 5 of the CDN migration: prefer the content-addressed URL from
|
|
433
|
+
// __DATA__.config.pageHashes (the publish handler emits it). Falls
|
|
434
|
+
// back to the legacy /{lang}/_pages/{route}.json shape when the map
|
|
435
|
+
// isn't present (older sites that haven't republished yet).
|
|
436
|
+
const hashes = this.website.config?.pageHashes
|
|
437
|
+
const hashedUrl = hashes?.[lang]?.[this.route]
|
|
438
|
+
|
|
439
|
+
let url
|
|
440
|
+
if (hashedUrl) {
|
|
441
|
+
url = `${base}${hashedUrl}`
|
|
442
|
+
} else {
|
|
443
|
+
const localePrefix = lang !== defaultLang ? `/${lang}` : ''
|
|
444
|
+
const routePath = this.route === '/' ? '/index' : this.route
|
|
445
|
+
url = `${base}${localePrefix}/_pages${routePath}.json`
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
const res = await fetch(url)
|
|
449
|
+
if (res.status === 404 && _shouldReloadOnHashed404(hashedUrl)) {
|
|
450
|
+
// Stale tab: this tab's __DATA__ map references a publish that
|
|
451
|
+
// no longer exists in R2. One reload usually picks up the fresh
|
|
452
|
+
// HTML (and a fresh map). Capped at 2 attempts to defend against
|
|
453
|
+
// a malformed publish where new HTML and new R2 also disagree.
|
|
454
|
+
window.location.reload()
|
|
455
|
+
return
|
|
456
|
+
}
|
|
434
457
|
if (!res.ok) {
|
|
435
458
|
console.warn(`[Page] Failed to load content for ${this.route}: ${res.status}`)
|
|
436
459
|
this._bodySections = [] // Mark as loaded (empty) to prevent retries
|
|
@@ -439,6 +462,11 @@ export default class Page {
|
|
|
439
462
|
const data = await res.json()
|
|
440
463
|
this._bodySections = data.sections || []
|
|
441
464
|
this._bodyBlocks = null // Reset lazy cache so getter rebuilds
|
|
465
|
+
// Reset the reload counter on a successful fetch so future stale
|
|
466
|
+
// tabs (across many publishes in one session) get fresh attempts.
|
|
467
|
+
if (typeof sessionStorage !== 'undefined') {
|
|
468
|
+
sessionStorage.removeItem('uniwebReloadCount')
|
|
469
|
+
}
|
|
442
470
|
} finally {
|
|
443
471
|
this._loadingContent = null
|
|
444
472
|
}
|
|
@@ -609,3 +637,33 @@ export default class Page {
|
|
|
609
637
|
return this.website.getVersionUrl(targetVersion, this.route)
|
|
610
638
|
}
|
|
611
639
|
}
|
|
640
|
+
|
|
641
|
+
/**
|
|
642
|
+
* Helper for the stale-tab 404→reload guard in Page.loadContent.
|
|
643
|
+
*
|
|
644
|
+
* Phase 5 of the CDN migration writes content-addressed `_pages/...-{hash}.json`
|
|
645
|
+
* files. Each publish wipes the prior hashes from R2 and writes fresh ones.
|
|
646
|
+
* A browser tab loaded against a previous publish carries a stale __DATA__
|
|
647
|
+
* map; on SPA navigation it'll request a hash that no longer exists.
|
|
648
|
+
* Reloading the tab pulls fresh HTML (and a fresh map). The session-scoped
|
|
649
|
+
* counter caps reloads at 2 so a malformed publish (where new HTML and new
|
|
650
|
+
* R2 disagree) doesn't trigger an infinite loop — after 2 failed reloads
|
|
651
|
+
* we render the synthetic 404 path instead.
|
|
652
|
+
*
|
|
653
|
+
* Only fires when the request was a hashed URL: legacy non-hashed 404s
|
|
654
|
+
* keep the prior "mark empty, log warning" behavior (they're not symptomatic
|
|
655
|
+
* of a stale-tab race; just a missing route).
|
|
656
|
+
*/
|
|
657
|
+
function _shouldReloadOnHashed404(hashedUrl) {
|
|
658
|
+
if (!hashedUrl) return false
|
|
659
|
+
if (typeof sessionStorage === 'undefined') return false
|
|
660
|
+
if (typeof window === 'undefined' || !window.location) return false
|
|
661
|
+
try {
|
|
662
|
+
const count = parseInt(sessionStorage.getItem('uniwebReloadCount') || '0', 10) || 0
|
|
663
|
+
if (count >= 2) return false
|
|
664
|
+
sessionStorage.setItem('uniwebReloadCount', String(count + 1))
|
|
665
|
+
return true
|
|
666
|
+
} catch {
|
|
667
|
+
return false
|
|
668
|
+
}
|
|
669
|
+
}
|