diff --git a/packages/next/client/performance-relayer.ts b/packages/next/client/performance-relayer.ts index 22ccf348cfbe8..1ec9449b46f78 100644 --- a/packages/next/client/performance-relayer.ts +++ b/packages/next/client/performance-relayer.ts @@ -47,13 +47,26 @@ function onReport(metric: Metric): void { type: 'application/x-www-form-urlencoded', }) const vitalsUrl = 'https://vitals.vercel-insights.com/v1/vitals' - ;(navigator.sendBeacon && navigator.sendBeacon(vitalsUrl, blob)) || + // Navigator has to be bound to ensure it does not error in some browsers + // https://xgwang.me/posts/you-may-not-know-beacon/#it-may-throw-error%2C-be-sure-to-catch + const send = navigator.sendBeacon && navigator.sendBeacon.bind(navigator) + + function fallbackSend() { fetch(vitalsUrl, { body: blob, method: 'POST', credentials: 'omit', keepalive: true, - }) + // console.error is used here as when the fetch fails it does not affect functioning of the app + }).catch(console.error) + } + + try { + // If send is undefined it'll throw as well. This reduces output code size. + send!(vitalsUrl, blob) + } catch (err) { + fallbackSend() + } } }