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 = 15000;
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 = 4;
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
- if (document.documentElement) {
43
- document.documentElement.style.backgroundColor = '#ffffff';
44
- }
45
- if (document.body) {
46
- document.body.style.backgroundColor = '#ffffff';
47
- document.body.innerHTML = ${JSON.stringify(reloadHtml)};
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); }, 500 * Math.pow(2, attempt));
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
- var lastRaw = sessionStorage.getItem(timeKey);
92
- var last = lastRaw ? Number(lastRaw) : null;
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
- // A reload that lands inside the same throttle window
109
- // means the previous recovery did not help: the assets
110
- // are momentarily unreadable at the edge rather than
111
- // stale. Waiting out the window and retrying lets the
112
- // page heal itself instead of stranding the visitor on
113
- // the error UI.
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));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cloudflare-next-intl",
3
- "version": "0.9.56",
3
+ "version": "0.9.58",
4
4
  "description": "Optimized Next Intl Package Special for App Router and Cloudflare",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",