Skip to content

ref(browser): Replace vendored web-vitals with web-vitals@6 dependency - #23070

Merged
logaretm merged 3 commits into
developfrom
awad/webvitals-dep-only
Aug 7, 2026
Merged

ref(browser): Replace vendored web-vitals with web-vitals@6 dependency#23070
logaretm merged 3 commits into
developfrom
awad/webvitals-dep-only

Conversation

@logaretm

@logaretm logaretm commented Aug 5, 2026

Copy link
Copy Markdown
Member

Replaces the vendored web-vitals fork with web-vitals@6 as a dependency.

No behavior change. browser-utils unit tests and the browser-integration web-vitals suites (LCP/CLS/INP/FCP/TTFB + streamed spans) pass, plus we still gate the bfcache web vitals from being sent, so identical behavior as of today.

A couple of concerns we discussed:

  • Bundle-size: It increased here because this is built against develop, once we add soft navs + bfcache vitals back our vendored version becomes larger and it required a similar size limit bumps in feat(browser): Experimental soft navigation web vitals support #22880
  • Browser Compatibility: The argument I led with was that web vitals as a concept only has a single definition which is the upstream repo, it is not a loose spec, it is a concrete implementation detail that is mostly led by chromium and we already have existing compatibility bugs with existing browsers like Firefox. So given webvitals upstream promises baseline-widely available (~30 months) this should be acceptable for this feature, since web vitals emissions behavior can drift and maintaining this has been a huge overhead for us.

@logaretm logaretm changed the title awad/webvitals dep only ref(browser): Replace vendored web-vitals with web-vitals@6 dependency Aug 5, 2026
@logaretm
logaretm force-pushed the awad/webvitals-dep-only branch from d23f63e to 64997f2 Compare August 5, 2026 16:47
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

⚠️ Warning: Base artifact is not the latest one, because the latest workflow run is not done yet. This may lead to incorrect results. Try to re-run all tests to get up to date results.

Path Size % Change Change
@sentry/browser 30.34 kB - -
@sentry/browser - with treeshaking flags 28.55 kB - -
@sentry/browser - with treeshaking flags tracing without tracing 26.86 kB - -
@sentry/browser (incl. Tracing) 49.13 kB +2.76% +1.32 kB 🔺
@sentry/browser (incl. Tracing + Span Streaming) 49.13 kB +2.74% +1.31 kB 🔺
@sentry/browser (incl. Tracing, Profiling) 53.92 kB +2.59% +1.36 kB 🔺
@sentry/browser (incl. Tracing, Replay) 88.42 kB +1.42% +1.24 kB 🔺
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 77.83 kB +1.59% +1.22 kB 🔺
@sentry/browser (incl. Tracing, Replay with Canvas) 93.13 kB +1.33% +1.22 kB 🔺
@sentry/browser (incl. Tracing, Replay, Feedback) 105.8 kB +1.2% +1.25 kB 🔺
@sentry/browser (incl. Feedback) 47.68 kB - -
@sentry/browser (incl. sendFeedback) 35.17 kB - -
@sentry/browser (incl. FeedbackAsync) 40.34 kB - -
@sentry/browser (incl. Metrics) 31.41 kB - -
@sentry/browser (incl. Logs) 31.66 kB - -
@sentry/browser (incl. Metrics & Logs) 32.32 kB - -
@sentry/react 32.15 kB - -
@sentry/react (incl. Tracing) 51.27 kB +2.42% +1.21 kB 🔺
@sentry/vue 35.45 kB - -
@sentry/vue (incl. Tracing) 51.05 kB +2.47% +1.23 kB 🔺
@sentry/svelte 30.37 kB - -
CDN Bundle 32.34 kB -0.01% -1 B 🔽
CDN Bundle (incl. Tracing) 49.66 kB +3.18% +1.53 kB 🔺
CDN Bundle (incl. Logs, Metrics) 33.87 kB -0.05% -14 B 🔽
CDN Bundle (incl. Tracing, Logs, Metrics) 50.96 kB +3.05% +1.5 kB 🔺
CDN Bundle (incl. Replay, Logs, Metrics) 74.39 kB +1.6% +1.17 kB 🔺
CDN Bundle (incl. Tracing, Replay) 87.19 kB +1.7% +1.46 kB 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 88.48 kB +1.68% +1.46 kB 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) 93.07 kB +1.65% +1.51 kB 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 94.32 kB +1.58% +1.47 kB 🔺
CDN Bundle - uncompressed 95.88 kB +0.01% +6 B 🔺
CDN Bundle (incl. Tracing) - uncompressed 148.98 kB +3.76% +5.4 kB 🔺
CDN Bundle (incl. Logs, Metrics) - uncompressed 100.47 kB -0.03% -30 B 🔽
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 152.96 kB +3.66% +5.4 kB 🔺
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 229.4 kB +1.87% +4.2 kB 🔺
CDN Bundle (incl. Tracing, Replay) - uncompressed 268.24 kB +2.06% +5.4 kB 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 272.2 kB +2.03% +5.4 kB 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 281.93 kB +1.95% +5.39 kB 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 285.89 kB +1.93% +5.39 kB 🔺
@sentry/nextjs (client) 53.8 kB +2.26% +1.19 kB 🔺
@sentry/sveltekit (client) 49.47 kB +2.51% +1.21 kB 🔺
@sentry/core/server 65.77 kB - -
@sentry/core/browser 52 kB - -
@sentry/node 119.43 kB - -
@sentry/node/import (ESM hook with diagnostics-channel injection) 0 B added added
@sentry/node - without tracing 83.42 kB - -
@sentry/aws-serverless 92.74 kB +0.01% +1 B 🔺
@sentry/cloudflare (withSentry) - minified 214.89 kB - -
@sentry/cloudflare (withSentry) 530.77 kB - -

View base workflow run

@logaretm
logaretm force-pushed the awad/webvitals-dep-only branch 5 times, most recently from b2a21b4 to a786f2c Compare August 5, 2026 19:44
@logaretm
logaretm marked this pull request as ready for review August 5, 2026 20:03
@logaretm
logaretm requested a review from a team as a code owner August 5, 2026 20:03
@logaretm
logaretm requested review from Lms24 and msonnb and removed request for a team August 5, 2026 20:03

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a786f2c. Configure here.

Comment thread packages/browser-utils/src/metrics/instrument.ts
Comment thread packages/browser-utils/src/metrics/instrument.ts Outdated
Upstream web-vitals v6 covers the metrics we vendored, so consume it as a
dependency instead of maintaining a ~1.9k-line in-tree copy. instrument.ts
imports the metric functions from the package and observes performance entries
with a local PerformanceObserver; the handful of generic browser helpers still
needed (getNavigationEntry, getVisibilityWatcher, whenIdleOrHidden, etc.) move
to metrics/web-vitals-helpers, and the rest of the vendored code is deleted.

No behavior change: browser-utils unit tests and the browser-integration
web-vitals suites (LCP/CLS/INP/FCP/TTFB + streamed spans) all pass.
The vendored `observe` helper wrapped PerformanceObserver callbacks in a
microtask to work around a Safari bug where the callback fires synchronously
during `observe()` instead of in a separate task
(GoogleChrome/web-vitals#277). The local
`instrumentPerformanceObserver` dropped that defer, so paint/longtask/event/
element handlers could run synchronously at init on affected Safari versions.
Upstream web-vitals@6 still ships this defer, so restore it here to match.
`instrumentInp` returns the `StopListening` cleanup from `onINP`, matching its
`instrumentCls`/`instrumentLcp`/`instrumentTtfb` siblings and the
`addMetricObserver` `instrumentFn` parameter, but was typed `void`. That
silently discarded the cleanup so a future `stopOnCallback` on INP would no-op.
@logaretm
logaretm force-pushed the awad/webvitals-dep-only branch from a7f3f5f to 732fddb Compare August 7, 2026 14:39
Comment on lines +325 to +335
// callback is invoked synchronously rather than in a separate task.
// See: https://github.com/GoogleChrome/web-vitals/issues/277
void Promise.resolve().then(() => {
triggerHandlers(type, { entries: list.getEntries() });
});
});
po.observe(options);
}
} catch {
// Unsupported entry type; nothing to observe.
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: A TypeError will be thrown in browsers where PerformanceObserver.supportedEntryTypes is undefined, causing performance observer initialization to fail silently.
Severity: MEDIUM

Suggested Fix

Use optional chaining to safely access the includes method: PerformanceObserver.supportedEntryTypes?.includes(type). This prevents the TypeError in environments where supportedEntryTypes is not defined, allowing the code to fail gracefully.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: packages/browser-utils/src/metrics/instrument.ts#L311-L335

Potential issue: The `instrumentPerformanceObserver` function directly accesses
`PerformanceObserver.supportedEntryTypes.includes(type)`. In environments where
`PerformanceObserver` exists but the `supportedEntryTypes` property is `undefined`
(e.g., older browsers), this will throw a `TypeError`. The surrounding `try/catch` block
will swallow the error, but it will silently prevent the performance observer from being
initialized, leading to a loss of performance metrics from affected user agents.

@logaretm
logaretm merged commit 8d480b6 into develop Aug 7, 2026
272 checks passed
@logaretm
logaretm deleted the awad/webvitals-dep-only branch August 7, 2026 15:19
logaretm added a commit that referenced this pull request Aug 7, 2026
Reorganizes `browser-utils/src` away from the catch-all `metrics/`
folder into clear domains: `instrumentation/` (dom/history/location/xhr
+ the PerformanceObserver layer), `web-vitals/` (tracking, spans, inp,
lcp, reportEvents, and the helpers merged into one utils), and
`performance/` (entries, element/user/resource timing, shared utils).

The reasoning is we will actually have some metric emitting logic in
there and we don't want it to be confused with pre-existing logic like
in #22397

Following up on pulling in `webvitals` as a dependency, I took this
chance to clean up our structure and it does have some minor bundle-size
improvements. The bundle increases are due to #23070 which explains
where the increase is coming from and why we are willing to absorb it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants