⚗️ Add soft navigation LCP tracking for route_change views - #4966
⚗️ Add soft navigation LCP tracking for route_change views#4966mormubis wants to merge 10 commits into
Conversation
…kspace app The nuxt-vue-router-v4-app is a generated app (gitignored, not registered in the root Yarn workspace). Playwright's webServer config starts every listed server before any test run, regardless of -g filtering. When Playwright spawned `yarn dev` in that directory, Yarn 4 traversed up to the workspace root and failed with "Package for nuxt-vue-router-v4-app@workspace:. not found" because the package isn't registered there. Switch to `yarn start` (nuxt preview of the pre-built .output/) which runs the built app directly via node and does not trigger Yarn workspace resolution.
…ntries, tighten E2E assertion, fix spec drift
| export interface RumInteractionContentfulPaintTiming { | ||
| entryType: RumPerformanceEntryType.INTERACTION_CONTENTFUL_PAINT | ||
| interactionId: number | ||
| largestContentfulPaint: RumLargestContentfulPaintTiming |
There was a problem hiding this comment.
Reused RumLargestContentfulPaintTiming here instead of a flat shape. The WICG spec types InteractionContentfulPaint.largestContentfulPaint as the full LargestContentfulPaint interface, not a subset, so this felt more accurate. Also gets toJSON() for free this way.
| } | ||
| biggestIcpSize = entry.largestContentfulPaint.size | ||
| const lcpEntry = entry.largestContentfulPaint | ||
| const largestContentfulPaint: LargestContentfulPaint = { |
There was a problem hiding this comment.
No subParts here on purpose. That breakdown (loadDelay/loadTime/renderDelay) needs a TTFB baseline from the hard nav, which doesn't really apply to a soft navigation. Left it undefined for now. Would it make more sense to have a soft-nav-specific breakdown eventually, or is undefined fine long term?
Bundles Sizes Evolution
|
|
Motivation
route_changeviews never report LCP today.trackInitialViewMetricsonly runs forinitial_load, so SPAs get zero LCP after the first page. Chrome's Soft Navigation API (stable since Chrome 151, no flag needed on their end) actually solves this now:soft-navigation+interaction-contentful-paintentries let us compute LCP per client-side navigation.There's an open GitHub issue for this (#2696) and an earlier draft PR (#4154) that only added a boolean
is_soft_navigationflag without touching LCP, which isn't really what the issue is asking for. This PR does the actual LCP computation.Changes
New
ExperimentalFeature.SOFT_NAVIGATIONflag. When enabled and the browser supports it,route_changeviews get atrackRouteChangeViewMetricstracker (same shape astrackInitialViewMetrics) that subscribes tosoft-navigationandinteraction-contentful-paintentries, correlates them byinteractionId, and fills inview.performance.lcp.*. No schema changes, reuses the existing field.The tricky part was figuring out when to stop listening for the
soft-navigationentry. It's per-view and Chrome fires it async, so a view whose interaction never actually produced a soft navigation would keep listening and could steal the next view's entry if I didn't unsubscribe it in time. Left a comment on that.There's a design doc and implementation plan committed under
docs/superpowers/specs/anddocs/superpowers/plans/if you want the full reasoning trail, including why I went with a per-view subscription instead of a global one.Also snuck in an unrelated one-line fix to
playwright.config.ts(ccf6ef335). Thenuxt-vue-router-v4-appE2E webServer was crashing locally, blocking every E2E test, not just mine. I know it's out of scope, happy to pull it into its own PR if you'd rather keep this one clean.Test instructions
enableExperimentalFeatures: ['soft_navigation']in your init config.history.pushStatein the same task (that's the heuristic Chrome uses to detect a soft navigation).route_changeview event,view.performance.lcp.timestampshould be populated.undefinedlike before.Unit tests:
yarn test:unit --spec packages/browser-rum-core/src/domain/view/viewMetrics/trackRouteChangeViewMetrics.spec.tsandyarn test:unit --spec packages/browser-rum-core/src/domain/view/trackViews.spec.tsE2E:
yarn test:e2e -g "soft navigation"(Chromium only). I couldn't get a clean run of this locally, looks like a VPN/network issue unrelated to the change (an already-merged, unrelated E2E test failed the exact same way). Would appreciate someone running this in CI or a clean env before merging.Checklist