cloudflare-next-intl 0.9.56 → 0.9.58
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.
|
@@ -9,7 +9,7 @@ const MAX_RECOVERY_ATTEMPTS = 2;
|
|
|
9
9
|
const BUILD_ID_KEY = 'buildId';
|
|
10
10
|
const BUILD_ID_SET_AT_KEY = 'buildIdSetAt';
|
|
11
11
|
const RECENT_BUILD_WINDOW_MS = 60000;
|
|
12
|
-
const RELOAD_THROTTLE_MS =
|
|
12
|
+
const RELOAD_THROTTLE_MS = 1000;
|
|
13
13
|
function currentBuildId() {
|
|
14
14
|
try {
|
|
15
15
|
return localStorage.getItem(BUILD_ID_KEY) ?? 'unknown';
|
|
@@ -20,15 +20,13 @@ export default function HelperScript() {
|
|
|
20
20
|
var timeKey = 'stale-deploy-recovery-time';
|
|
21
21
|
var countKey = 'stale-deploy-recovery-count';
|
|
22
22
|
var maxAttempts = 3;
|
|
23
|
-
var throttleMs = 15000;
|
|
24
23
|
var attemptedThisLoad = false;
|
|
25
|
-
var retryScheduled = false;
|
|
26
24
|
// Set by the resource-error listener: the first same-origin
|
|
27
25
|
// chunk that failed. Reloading is pointless until that URL
|
|
28
26
|
// answers with real JavaScript again, so it doubles as the
|
|
29
27
|
// health probe below.
|
|
30
28
|
var probeUrl = null;
|
|
31
|
-
var maxProbes =
|
|
29
|
+
var maxProbes = 3;
|
|
32
30
|
function isStale(msg) {
|
|
33
31
|
if (msg === undefined || msg === null) return true;
|
|
34
32
|
msg = String(msg).toLowerCase();
|
|
@@ -37,15 +35,21 @@ export default function HelperScript() {
|
|
|
37
35
|
}
|
|
38
36
|
return false;
|
|
39
37
|
}
|
|
38
|
+
// Cover the page, never replace it. Wiping document.body used
|
|
39
|
+
// to be safe because a reload followed immediately; now that a
|
|
40
|
+
// probe can run for a few seconds first, React keeps rendering
|
|
41
|
+
// against the tree and every removeChild/insertBefore throws,
|
|
42
|
+
// which crashes it into the very error UI this is hiding.
|
|
43
|
+
var overlayId = 'cfni-stale-deploy-overlay';
|
|
40
44
|
function showOverlay() {
|
|
41
45
|
try {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
var root = document.documentElement;
|
|
47
|
+
if (!root || document.getElementById(overlayId)) return;
|
|
48
|
+
var el = document.createElement('div');
|
|
49
|
+
el.id = overlayId;
|
|
50
|
+
el.setAttribute('style', 'position:fixed;inset:0;z-index:2147483647;background:#ffffff;');
|
|
51
|
+
el.innerHTML = ${JSON.stringify(reloadHtml)};
|
|
52
|
+
(document.body || root).appendChild(el);
|
|
49
53
|
} catch (e) {}
|
|
50
54
|
}
|
|
51
55
|
function doReload() {
|
|
@@ -77,7 +81,7 @@ export default function HelperScript() {
|
|
|
77
81
|
console.warn('[StaleDeploy early-catch] Asset still unhealthy after', attempt + 1, 'probes - reloading anyway:', String(err));
|
|
78
82
|
return doReload();
|
|
79
83
|
}
|
|
80
|
-
setTimeout(function() { probeThenReload(attempt + 1); },
|
|
84
|
+
setTimeout(function() { probeThenReload(attempt + 1); }, 300 * Math.pow(2, attempt));
|
|
81
85
|
});
|
|
82
86
|
}
|
|
83
87
|
function recover(msg, source) {
|
|
@@ -88,11 +92,8 @@ export default function HelperScript() {
|
|
|
88
92
|
if (!stale) return;
|
|
89
93
|
var buildId = localStorage.getItem('buildId') || 'unknown';
|
|
90
94
|
var marker = sessionStorage.getItem(key);
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
var throttled = last !== null && (Date.now() - last) < throttleMs;
|
|
94
|
-
// Attempts are counted per build id: the 1st and 2nd
|
|
95
|
-
// page load may each recover, the 3rd falls through to
|
|
95
|
+
// Attempts are counted per build id: the first few
|
|
96
|
+
// page loads may each recover, then it falls through to
|
|
96
97
|
// the error UI. A new deploy resets the count.
|
|
97
98
|
var sameBuild = marker === buildId;
|
|
98
99
|
var attempts = 0;
|
|
@@ -105,22 +106,12 @@ export default function HelperScript() {
|
|
|
105
106
|
console.warn('[StaleDeploy early-catch] Skipping reload, attempts exhausted for buildId:', buildId, attempts);
|
|
106
107
|
return;
|
|
107
108
|
}
|
|
108
|
-
//
|
|
109
|
-
//
|
|
110
|
-
//
|
|
111
|
-
//
|
|
112
|
-
//
|
|
113
|
-
//
|
|
114
|
-
if (sameBuild && throttled) {
|
|
115
|
-
if (retryScheduled) return;
|
|
116
|
-
retryScheduled = true;
|
|
117
|
-
var wait = throttleMs - (Date.now() - last);
|
|
118
|
-
if (!(wait > 0)) wait = 0;
|
|
119
|
-
console.warn('[StaleDeploy early-catch] Throttled for buildId:', buildId, '- retrying in', wait, 'ms');
|
|
120
|
-
showOverlay();
|
|
121
|
-
setTimeout(function() { retryScheduled = false; recover(msg, source); }, wait + 250);
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
109
|
+
// No time-based throttle: the probe below already
|
|
110
|
+
// paces the retry and refuses to reload until the asset
|
|
111
|
+
// is readable, so a clock-based wait only strands the
|
|
112
|
+
// visitor on the overlay for the rest of the window.
|
|
113
|
+
// attemptedThisLoad stops a burst within one load and
|
|
114
|
+
// maxAttempts stops a reload loop across loads.
|
|
124
115
|
attemptedThisLoad = true;
|
|
125
116
|
sessionStorage.setItem(key, buildId);
|
|
126
117
|
sessionStorage.setItem(countKey, String(attempts + 1));
|