ref(browser): Replace vendored web-vitals with web-vitals@6 dependency - #23070
ref(browser): Replace vendored web-vitals with web-vitals@6 dependency#23070logaretm wants to merge 1 commit into
Conversation
d23f63e to
64997f2
Compare
size-limit report 📦
|
43daa35 to
b2a21b4
Compare
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.
b2a21b4 to
a786f2c
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ 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.
| } | ||
| } catch { | ||
| // Unsupported entry type; nothing to observe. | ||
| } |
There was a problem hiding this comment.
Safari observer sync callback regression
Medium Severity
Replacing the vendored observe helper dropped its Safari workaround that deferred PerformanceObserver callbacks with a microtask. Upstream web-vitals still defers these callbacks, but this local path for paint, longtask, event, and similar entries now runs handlers synchronously on affected Safari versions when buffered: true is used, which can change init-time timing for FP/FCP and related metrics.
Reviewed by Cursor Bugbot for commit a786f2c. Configure here.
| function instrumentInp(): void { | ||
| return onINP(metric => { | ||
| triggerHandlers('inp', { | ||
| metric, | ||
| }); | ||
| _previousInp = metric; | ||
| }); | ||
| return onINP( | ||
| withoutBfcache(metric => { | ||
| triggerHandlers('inp', { | ||
| metric, | ||
| }); | ||
| _previousInp = metric; | ||
| }), | ||
| ); | ||
| } |
There was a problem hiding this comment.
Bug: The instrumentInp function is incorrectly typed to return void but actually returns a StopListening function, preventing listener cleanup.
Severity: MEDIUM
Suggested Fix
Update the function signature of instrumentInp to correctly declare its return type as StopListening. Change function instrumentInp(): void to function instrumentInp(): StopListening.
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#L279-L288
Potential issue: The `instrumentInp` function is declared with a return type of `void`,
but its implementation returns a `StopListening` function from `onINP(...)`. This type
mismatch causes the returned cleanup function to be discarded when `instrumentInp` is
called within `addMetricObserver`. As a result, the `stopListening` variable becomes
`undefined`, and the cleanup logic in `getCleanupCallback` never executes the
`stopListening()` call. This prevents the INP metric listener from being stopped, unlike
other metrics (`CLS`, `LCP`) which are correctly typed.
Did we get this right? 👍 / 👎 to inform future reviews.


Replaces the vendored web-vitals fork with
web-vitals@6as 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: