From 9cae993837df0ad9f97614b1dc2b5878c9566b24 Mon Sep 17 00:00:00 2001 From: Bryce Kalow Date: Thu, 25 Sep 2025 23:27:49 -0500 Subject: [PATCH 1/3] Intelligent retries for existing clerk-js script --- packages/shared/src/loadClerkJsScript.ts | 73 ++++++++++++++++++++---- 1 file changed, 62 insertions(+), 11 deletions(-) diff --git a/packages/shared/src/loadClerkJsScript.ts b/packages/shared/src/loadClerkJsScript.ts index 68f81af1778..5fb870709ac 100644 --- a/packages/shared/src/loadClerkJsScript.ts +++ b/packages/shared/src/loadClerkJsScript.ts @@ -59,6 +59,40 @@ function isClerkProperlyLoaded(): boolean { return typeof clerk === 'object' && typeof clerk.load === 'function'; } +/** + * Checks if an existing script has a request error using Performance API. + * + * @param scriptUrl - The URL of the script to check. + * @returns True if the script has failed to load due to a network/HTTP error. + */ +function hasScriptRequestError(scriptUrl: string): boolean { + if (typeof window === 'undefined' || !window.performance) { + return false; + } + + const entries = performance.getEntries() as PerformanceResourceTiming[]; + const scriptEntry = entries.find(entry => entry.name === scriptUrl); + + if (!scriptEntry) { + return false; + } + + // transferSize === 0 with responseEnd === 0 indicates network failure + // transferSize === 0 with responseEnd > 0 might be a 4xx/5xx error or blocked request + if (scriptEntry.transferSize === 0 && scriptEntry.decodedBodySize === 0) { + // If there was no response at all, it's definitely an error + if (scriptEntry.responseEnd === 0) { + return true; + } + // If we got a response but no content, likely an HTTP error (4xx/5xx) + if (scriptEntry.responseEnd > 0 && scriptEntry.responseStart > 0) { + return true; + } + } + + return false; +} + /** * Waits for Clerk to be properly loaded with a timeout mechanism. * Uses polling to check if Clerk becomes available within the specified timeout. @@ -117,11 +151,13 @@ function waitForClerkWithTimeout(timeoutMs: number): Promise('script[data-clerk-js-script]'); - - if (existingScript) { - return waitForClerkWithTimeout(timeout); - } - if (!opts?.publishableKey) { errorThrower.throwMissingPublishableKeyError(); return null; } + const scriptUrl = clerkJsScriptUrl(opts); + const existingScript = document.querySelector('script[data-clerk-js-script]'); + + if (existingScript) { + // Check if the existing script has a request error + const hasError = hasScriptRequestError(scriptUrl); + + if (hasError) { + // Request error detected - remove failed script and initiate loadScript immediately + existingScript.remove(); + } else { + // No request error - wait for timeout, then retry if needed + try { + return await waitForClerkWithTimeout(timeout); + } catch { + // Timeout expired without success - remove script and retry + existingScript.remove(); + } + } + } + const loadPromise = waitForClerkWithTimeout(timeout); - loadScript(clerkJsScriptUrl(opts), { + loadScript(scriptUrl, { async: true, crossOrigin: 'anonymous', nonce: opts.nonce, From 7d0b4fe7514ec6b4550d25fc5f10f85722afa24d Mon Sep 17 00:00:00 2001 From: Bryce Kalow Date: Thu, 25 Sep 2025 23:29:18 -0500 Subject: [PATCH 2/3] remove comments --- packages/shared/src/loadClerkJsScript.ts | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/packages/shared/src/loadClerkJsScript.ts b/packages/shared/src/loadClerkJsScript.ts index 5fb870709ac..845f6a6ba58 100644 --- a/packages/shared/src/loadClerkJsScript.ts +++ b/packages/shared/src/loadClerkJsScript.ts @@ -189,18 +189,12 @@ const loadClerkJsScript = async (opts?: LoadClerkJsScriptOptions): Promise('script[data-clerk-js-script]'); if (existingScript) { - // Check if the existing script has a request error - const hasError = hasScriptRequestError(scriptUrl); - - if (hasError) { - // Request error detected - remove failed script and initiate loadScript immediately + if (hasScriptRequestError(scriptUrl)) { existingScript.remove(); } else { - // No request error - wait for timeout, then retry if needed try { return await waitForClerkWithTimeout(timeout); } catch { - // Timeout expired without success - remove script and retry existingScript.remove(); } } From 6b3efd1639d10fa340f7399f125c24acce0f11f8 Mon Sep 17 00:00:00 2001 From: Bryce Kalow Date: Fri, 26 Sep 2025 15:48:04 -0500 Subject: [PATCH 3/3] tweak heuristic --- packages/shared/src/loadClerkJsScript.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/shared/src/loadClerkJsScript.ts b/packages/shared/src/loadClerkJsScript.ts index 845f6a6ba58..fff2d8b6b0b 100644 --- a/packages/shared/src/loadClerkJsScript.ts +++ b/packages/shared/src/loadClerkJsScript.ts @@ -88,6 +88,10 @@ function hasScriptRequestError(scriptUrl: string): boolean { if (scriptEntry.responseEnd > 0 && scriptEntry.responseStart > 0) { return true; } + + if (scriptEntry.responseStatus === 0) { + return true; + } } return false;