
James HammerChrome 151 went stable on July 28. Three weeks later, most of the coverage of that release has...
Chrome 151 went stable on July 28. Three weeks later, most of the coverage of that release has already moved on, but one change in it deserves more attention than it's getting: real, unflagged support for measuring Core Web Vitals on client-side route changes. If you build or maintain a React, Vue, or Next.js site, this closes a measurement gap that's existed since Core Web Vitals launched, and it comes with a catch worth understanding before you rely on it.
LCP, INP, and CLS were designed around a hard navigation. A fresh document request, a clean timing origin, a browser that knows a new page just loaded. Single-page apps were never built that way. A user clicks from a product listing to checkout, the URL updates, new content renders, and the browser never fires a real navigation event underneath it. The Performance API only ever saw the first thing that loaded, usually the framework's boot-up shell or a loading state, and stayed quiet for every route change that followed. Field dashboards built on that data have spent years reporting a great LCP for the one moment users cared about least.
Chrome ran a series of origin trials through versions 147 to 149 to test a fix. The Soft Navigations API adds a heuristic: watch for a user interaction, a URL change, and a subsequent paint, and treat that combination as a navigation in its own right. Chrome 151 is where it stopped being experimental. New soft-navigation and interaction-contentful-paint entries now show up in the Performance Timeline by default, each soft navigation gets its own timing origin, and LCP, INP, and CLS get measured against the route that actually happened rather than folded into whatever loaded first. The web-vitals library, which most RUM tools build on, added support for this on July 21, ahead of the browser release itself.
The part most writeups skip past
Nearly everything published about this launch treats “you can measure it now” as the whole story. It isn't. Buried in Chrome's own developer documentation for this feature is a note about what happens after the measurement: the team hasn't decided how, or whether, this data will flow into the Chrome UX Report, and they've said they'll share more when there's something to share.
CrUX matters here because it's not just another metrics dashboard. It's the specific dataset Google draws from for the Core Web Vitals ranking signal, and it's what feeds the field data shown in PageSpeed Insights and the Search Console Core Web Vitals report. Right now, none of that includes soft navigations. It only sees the first hard load.
Which creates a real, current split. Wire up the latest web-vitals release today and you can find out, with route-level accuracy, whether your checkout flow's client-side LCP is actually bad. Search Console, meanwhile, keeps reporting on the same site as if that route barely exists, because as far as CrUX is concerned it doesn't. Both numbers are correct. They're just answering different questions: one reflects what a person experienced clicking through your app, the other reflects what Google is currently scoring you on. For any team that has treated Search Console as its only source of truth for Core Web Vitals, this is worth flagging internally before it turns into a confusing conversation with a client.
What changes in your code
If a project already uses web-vitals, the update is small:
import { onLCP, onINP, onCLS } from 'web-vitals';
function sendToAnalytics(metric) {
navigator.sendBeacon('/api/vitals', JSON.stringify({
name: metric.name,
value: metric.value,
rating: metric.rating,
navigationType: metric.navigationType, // now includes 'soft-navigation'
route: window.location.pathname,
}));
}
onLCP(sendToAnalytics);
onINP(sendToAnalytics);
onCLS(sendToAnalytics);
metric.navigationType is the field worth building a dashboard around. It tells you whether a given reading came from the initial hard load or a route change afterward, so a portfolio of routes can finally be judged on their own numbers instead of one aggregate figure dominated by whatever loaded first.
Two limits are worth building around from day one. Safari and Firefox haven't implemented this, so any dashboard depending on it needs a fallback for non-Chromium traffic rather than blank data. And Chrome's detection heuristic, an interaction plus a URL change plus a paint, will occasionally get it wrong in both directions: a route change with no meaningful content update might register as a full navigation, while a significant in-page update that skips the URL might not register at all. Test the heuristic against a specific app's own routing behavior before trusting the numbers it produces.
It's not only framework SPAs
The heuristic Chrome uses doesn't check which framework, if any, is running. It's watching for the interaction, URL change, and paint pattern, regardless of what produced it. A WordPress site with AJAX-driven filtering, a product filter on a WooCommerce catalog, an events calendar, a live search panel, can trigger the same detection the moment it updates the URL through the History API, even though nobody on the team would describe that site as a single-page app. That's a new category of thing worth checking during a performance or SEO audit on a WordPress build. Anyone offering WordPress development services on AJAX-heavy sites is going to run into pages where this kind of interactivity has never shown up in Core Web Vitals field data at all, simply because there was no mechanism to catch it until now.
Put plainly: the measurement gap that's made SPA performance data unreliable for years finally has a real fix at the platform level. The fix shipped in the browser weeks before anyone can say when, or if, it shows up in the dataset Google actually ranks sites on. Anyone relying on Search Console as the only signal here is still missing the same routes they were missing last month. The difference now is there's a way to go check for yourself.
Sources
Chrome for Developers: Measuring soft navigations
Chrome for Developers: Final Soft Navigations origin trial starting in Chrome 147
web-vitals on GitHub