v139 · SPA Navigation Observer
SPA Navigation Observer
Navigate a simulated SPA and watch each client-side route change produce a SoftNavigationEntry with a unique navigationId — the key that ties LCP, INP, and CLS measurements to a specific route.
chrome://flags/#soft-navigation-heuristics to see real SoftNavigationEntry objects. The demo detects support and falls back to a simulation when unavailable.
Home
Welcome to the simulated SPA. Click the nav items above to trigger soft navigations and observe the performance entries in the panel on the right.
Products
Each route change fires a heuristic-detected soft navigation. The browser assigns a unique navigationId shared by all Web Vitals entries for this route.
Cart
The SoftNavigationEntry carries the new URL, interaction timestamp, and paint timing — everything you need to attribute vitals to the right route.
Account
Notice how each entry gets a monotonically increasing interactionId. This links back to the pointer/keyboard event that triggered the navigation.
Click a nav item in the SPA to trigger a soft navigation…
API code
// Observe soft-navigation entries
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log(entry.entryType); // 'soft-navigation'
console.log(entry.name); // new URL, e.g. 'https://shop.example/products'
console.log(entry.startTime); // DOMHighResTimeStamp of the interaction
console.log(entry.duration); // time to "navigation complete" (LCP settled)
console.log(entry.navigationId); // unique ID for this soft navigation
console.log(entry.interactionId); // pointer/keyboard event ID that triggered it
}
});
observer.observe({ type: 'soft-navigation', buffered: true });
// Correlate with other vitals entries using navigationId:
const lcpObserver = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// entry.navigationId links this LCP to its SoftNavigationEntry
console.log(`LCP ${entry.startTime}ms — nav ${entry.navigationId}`);
}
});
lcpObserver.observe({ type: 'largest-contentful-paint', buffered: true });
see also
- Core Web Vitals Dashboard — correlate vitals across soft navigations
- ChromeStatus entry
- WICG/soft-navigations spec
- Chrome Developers — Soft Navigations experiment