sitespeedio / sitespeedio/sitespeed.io

Soft navigations: Total Blocking Time is document-cumulative, not per route

Open
#4,892 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
JavaScript
Stars
5k
Forks
624
Avg merge
4h 8m
Merged PRs (30d)
2

Description

Have you read the documentation?
URL

http://localhost:8099 (spin up application to be tested in one python command)

What are you trying to accomplish

I want to get correct per-route TBT metrics during SPA soft navigations.
Currently, TBT grows monotonically across a multi-step user journey, causing later pages to fail performance thresholds due to accumulated work from previous routes. I want to scope long tasks to their respective navigationId so that TBT is calculated independently for each soft navigation.

Attached archive with two reports: local Mac OS run and run via Docker and .html file to spin up reproducible local web site in 1 click.
Please let me know if it is inconvenient for you to run the tested website locally, I will try to deploy it somewhere publicly, as per your guide.
soft-nav-tbt.zip

Summary

On a page measured as a soft navigation, cpu.longTasks.totalBlockingTime (and therefore
googleWebVitals.totalBlockingTime, the HAR's _googleWebVitals.totalBlockingTime, and the
Total Blocking Time card on the HTML summary) is the sum of every long task in the
document's lifetime
, not the ones belonging to the route change being measured. The value
therefore climbs monotonically across a journey, and on the summary page every page after
the first is graded against a threshold using a number that includes its predecessors' work.

CLS and INP are already scoped correctly for soft navigations, via
entry.navigationId. Long tasks are not.

Reproducing

cd docs/repro/soft-nav-tbt
python3 -m http.server 8099            # any static server; a real origin is required

sitespeed.io --multi test.mjs -n 1 --spa \
  --browsertime.timeouts.pageCompleteCheck 10000

Docker:

python3 -m http.server 8099 &
docker run --rm -v "$(pwd):/sitespeed.io" \
  -e REPRO_ORIGIN=http://host.docker.internal:8099 \
  sitespeedio/sitespeed.io:42.6.0 \
  --multi test.mjs -n 1 --spa --browsertime.timeouts.pageCompleteCheck 10000

Every route blocks the main thread for the same 250 ms, so a correct per-route TBT is
roughly constant at ~200 ms (250 minus the 50 ms threshold).

Expected vs actual

Actual output from sitespeedio/sitespeed.io:42.6.0:

route-one:   browsertime reports TBT=451 ms  | correct per-route TBT=200 ms | document-wide sum=451 ms
route-two:   browsertime reports TBT=651 ms  | correct per-route TBT=200 ms | document-wide sum=651 ms
route-three: browsertime reports TBT=851 ms  | correct per-route TBT=200 ms | document-wide sum=851 ms
route-four:  browsertime reports TBT=1051 ms | correct per-route TBT=200 ms | document-wide sum=1051 ms
route expected TBT reported TBT
one 200 ms 451 ms
two 200 ms 651 ms
three 200 ms 851 ms
four 200 ms 1051 ms

Three things to note. The correct per-route value is constant, as it must be when every
route does identical work. The reported value grows by exactly one route's cost each time.
And it equals the document-wide sum exactly, which is the whole claim.

One detail that matters if you modify index.html: the 250 ms of work is deferred with
setTimeout(..., 0). Blocking synchronously inside the click handler would run in the same
task as the interaction, before the soft navigation is committed, and Chrome would attribute
that long task to the previous navigationId — which both misrepresents how real routers
behave (they render in later tasks) and makes the per-route attribution untestable.

Cause

Two things combine.

1. The collector replays the whole buffer. lib/chrome/webdriver/chromium.js:

observer.observe({type: 'longtask', buffered: true});
const entries = observer.takeRecords();

buffered: true delivers every long task the document has produced. A soft navigation never
replaces the document, so each measurement re-collects the complete history. The entries are
then copied field by field into this.longTaskInfo, and navigationId is not among the
copied fields.

2. The lower bound is a soft-nav-relative time compared against absolute ones.
lib/chrome/longTaskMetrics.js:

if (firstContentfulPaint && longTask.startTime > firstContentfulPaint) {
  totalBlockingTime += longTask.duration - (options.minLongTaskLength || 50);
}

On a soft-navigation page firstContentfulPaint has been replaced with the value measured
from the click (a few tens of ms), while longTask.startTime is absolute, relative to
the original hard navigation (often tens of thousands of ms). So the filter admits
essentially every task in the document.

Suggested fix

Long-task entries do carry navigationId in Chrome 151 (test.mjs asserts this and prints
it), and it matches the navigationId of the soft navigation during which the task ran. So
the same mechanism browserscripts/timings/softNavigations.js already uses for CLS and INP
applies:

  1. In the collector, copy event.navigationId alongside duration / name / startTime.
  2. In longTaskMetrics.js, when the page is a soft navigation, keep only tasks whose
    navigationId matches that soft navigation, and drop the startTime > FCP comparison for
    those pages (the units are not comparable).

cpu.longTasks.tasks, totalDuration, maxPotentialFid and lastLongTask are cumulative
for the same reason and would be fixed by the same filter. The
beforeFirstPaint / beforeFirstContentfulPaint / beforeLargestContentfulPaint /
afterLoadEventEnd buckets compare absolute task timestamps against soft-nav-relative paint
times, so they need either the same treatment or to be omitted on soft-navigation pages.

Versions

Observed with sitespeed.io 42.6.0, browsertime 28.3.0, Chrome 151.0.7922.75 on
linux/amd64 and linux/arm64 (the official sitespeedio/sitespeed.io:42.6.0 image).

What browser did you use?

Chrome

How to reproduce
## Reproducing


cd docs/repro/soft-nav-tbt
python3 -m http.server 8099            # any static server; a real origin is required

sitespeed.io --multi test.mjs -n 1 --spa \
  --browsertime.timeouts.pageCompleteCheck 10000


Docker:


python3 -m http.server 8099 &
docker run --rm -v "$(pwd):/sitespeed.io" \
  -e REPRO_ORIGIN=http://host.docker.internal:8099 \
  sitespeedio/sitespeed.io:42.6.0 \
  --multi test.mjs -n 1 --spa --browsertime.timeouts.pageCompleteCheck 10000
Log output
user@macbook soft-nav-tbt % sitespeed.io --multi test.mjs -n 1 --spa \
  --browsertime.timeouts.pageCompleteCheck 10000
[2026-09-09 13:25:40] INFO: Versions OS: darwin 25.6.0 nodejs: v22.15.0 sitespeed.io: 42.6.0 browsertime: 28.3.0 coach: 9.2.1
[2026-09-09 13:25:40] INFO: Running tests using Chrome - 1 iteration(s)
[2026-09-09 13:25:46] INFO: Testing url http://localhost:8099/ iteration 1
[2026-09-09 13:25:53] INFO: Take after page complete check screenshot
[2026-09-09 13:25:54] INFO: Take cumulative layout shift screenshot
[2026-09-09 13:25:54] INFO: Take largest contentful paint screenshot
[2026-09-09 13:25:55] INFO: Start to measure route-one
[2026-09-09 13:26:06] INFO: Take after page complete check screenshot
[2026-09-09 13:26:06] INFO: Take cumulative layout shift screenshot
[2026-09-09 13:26:07] INFO: Take largest contentful paint screenshot
[2026-09-09 13:26:07] INFO: route-one: browsertime reports TBT=200 ms over 1 long tasks | correct per-route TBT=200 ms over 1 task(s) | document-wide sum=200 ms (longTask.navigationId present: true)
[2026-09-09 13:26:07] INFO: Start to measure route-two
[2026-09-09 13:26:18] INFO: Take after page complete check screenshot
[2026-09-09 13:26:18] INFO: Take cumulative layout shift screenshot
[2026-09-09 13:26:19] INFO: Take largest contentful paint screenshot
[2026-09-09 13:26:19] INFO: route-two: browsertime reports TBT=400 ms over 2 long tasks | correct per-route TBT=200 ms over 1 task(s) | document-wide sum=400 ms (longTask.navigationId present: true)
[2026-09-09 13:26:19] INFO: Start to measure route-three
[2026-09-09 13:26:31] INFO: Take after page complete check screenshot
[2026-09-09 13:26:31] INFO: Take cumulative layout shift screenshot
[2026-09-09 13:26:31] INFO: Take largest contentful paint screenshot
[2026-09-09 13:26:31] INFO: route-three: browsertime reports TBT=600 ms over 3 long tasks | correct per-route TBT=200 ms over 1 task(s) | document-wide sum=600 ms (longTask.navigationId present: true)
[2026-09-09 13:26:31] INFO: Start to measure route-four
[2026-09-09 13:26:43] INFO: Take after page complete check screenshot
[2026-09-09 13:26:43] INFO: Take cumulative layout shift screenshot
[2026-09-09 13:26:43] INFO: Take largest contentful paint screenshot
[2026-09-09 13:26:44] INFO: route-four: browsertime reports TBT=800 ms over 4 long tasks | correct per-route TBT=200 ms over 1 task(s) | document-wide sum=800 ms (longTask.navigationId present: true)
[2026-09-09 13:26:44] INFO: EXPECTED: every route blocks for the same 250 ms, so per-route TBT should be ~200 ms on each. ACTUAL: the reported value grows monotonically because it is the document-wide sum.
[2026-09-09 13:26:46] INFO: http://localhost:8099/ 2 requests, TTFB: 45ms, firstPaint: 480ms, FCP: 480ms, DOMContentLoaded: 350ms, LCP: 480ms, CLS: 0, TBT: 0ms, CPUBenchmark: 32ms, Load: 350ms
[2026-09-09 13:26:46] INFO: http://localhost:8099/one TTFB: 45ms, firstPaint: 480ms, FCP: 25ms, DOMContentLoaded: 350ms, LCP: 25ms, CLS: 0, TBT: 200ms, CPUBenchmark: 32ms, Load: 350ms
[2026-09-09 13:26:46] INFO: http://localhost:8099/two TTFB: 45ms, firstPaint: 480ms, FCP: 30ms, DOMContentLoaded: 350ms, LCP: 30ms, CLS: 0, TBT: 400ms, CPUBenchmark: 31ms, Load: 350ms
[2026-09-09 13:26:46] INFO: http://localhost:8099/three TTFB: 45ms, firstPaint: 480ms, FCP: 23ms, DOMContentLoaded: 350ms, LCP: 23ms, CLS: 0, TBT: 600ms, CPUBenchmark: 32ms, Load: 350ms
[2026-09-09 13:26:46] INFO: http://localhost:8099/four TTFB: 45ms, firstPaint: 480ms, FCP: 26ms, DOMContentLoaded: 350ms, LCP: 26ms, CLS: 0, TBT: 800ms, CPUBenchmark: 32ms, Load: 350ms
[2026-09-09 13:26:46] INFO: The server responded with a 404 status code for http://localhost:8099/favicon.ico
[2026-09-09 13:26:46] ERROR: Could not generate coach data Error: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
    at Function.from (<anonymous>)
    at Object.convert (/Users/user/.npm-packages/lib/node_modules/sitespeed.io/node_modules/pagexray/lib/index.js:74:27)
    at getPagesFromHar (file:///Users/user/.npm-packages/lib/node_modules/sitespeed.io/node_modules/coach-core/lib/index.js:18:19)
    at analyseHar (file:///Users/user/.npm-packages/lib/node_modules/sitespeed.io/node_modules/coach-core/lib/index.js:70:5)
    at async BrowsertimePlugin.processMessage (file:///Users/user/.npm-packages/lib/node_modules/sitespeed.io/lib/plugins/browsertime/index.js:562:39)
[2026-09-09 13:26:46] INFO: The server responded with a 404 status code for http://localhost:8099/favicon.ico
[2026-09-09 13:26:46] ERROR: Could not generate coach data Error: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
    at Function.from (<anonymous>)
    at Object.convert (/Users/user/.npm-packages/lib/node_modules/sitespeed.io/node_modules/pagexray/lib/index.js:74:27)
    at getPagesFromHar (file:///Users/user/.npm-packages/lib/node_modules/sitespeed.io/node_modules/coach-core/lib/index.js:18:19)
    at analyseHar (file:///Users/user/.npm-packages/lib/node_modules/sitespeed.io/node_modules/coach-core/lib/index.js:70:5)
    at async BrowsertimePlugin.processMessage (file:///Users/user/.npm-packages/lib/node_modules/sitespeed.io/lib/plugins/browsertime/index.js:562:39)
[2026-09-09 13:26:46] INFO: The server responded with a 404 status code for http://localhost:8099/favicon.ico
[2026-09-09 13:26:46] ERROR: Could not generate coach data Error: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
    at Function.from (<anonymous>)
    at Object.convert (/Users/user/.npm-packages/lib/node_modules/sitespeed.io/node_modules/pagexray/lib/index.js:74:27)
    at getPagesFromHar (file:///Users/user/.npm-packages/lib/node_modules/sitespeed.io/node_modules/coach-core/lib/index.js:18:19)
    at analyseHar (file:///Users/user/.npm-packages/lib/node_modules/sitespeed.io/node_modules/coach-core/lib/index.js:70:5)
    at async BrowsertimePlugin.processMessage (file:///Users/user/.npm-packages/lib/node_modules/sitespeed.io/lib/plugins/browsertime/index.js:562:39)
[2026-09-09 13:26:46] INFO: The server responded with a 404 status code for http://localhost:8099/favicon.ico
[2026-09-09 13:26:46] ERROR: Could not generate coach data Error: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
    at Function.from (<anonymous>)
    at Object.convert (/Users/user/.npm-packages/lib/node_modules/sitespeed.io/node_modules/pagexray/lib/index.js:74:27)
    at getPagesFromHar (file:///Users/user/.npm-packages/lib/node_modules/sitespeed.io/node_modules/coach-core/lib/index.js:18:19)
    at analyseHar (file:///Users/user/.npm-packages/lib/node_modules/sitespeed.io/node_modules/coach-core/lib/index.js:70:5)
    at async BrowsertimePlugin.processMessage (file:///Users/user/.npm-packages/lib/node_modules/sitespeed.io/lib/plugins/browsertime/index.js:562:39)
[2026-09-09 13:26:46] INFO: The server responded with a 404 status code for http://localhost:8099/favicon.ico
[2026-09-09 13:26:47] INFO: HTML stored in /Users/user/Documents/GIT/sitespeed-ui-performance/docs/repro/soft-nav-tbt/sitespeed-result/test_mjs/2026-09-09-13-25-40
user@macbook soft-nav-tbt % docker run --rm -v "$(pwd):/sitespeed.io" \
  -e REPRO_ORIGIN=http://host.docker.internal:8099 \
  sitespeedio/sitespeed.io:42.6.0 \
  --multi test.mjs -n 1 --spa --browsertime.timeouts.pageCompleteCheck 10000
Unable to find image 'sitespeedio/sitespeed.io:42.6.0' locally
42.6.0: Pulling from sitespeedio/sitespeed.io
Digest: sha256:075311541bfd68e299f0ae451c4520bd2ea1e00bc3f5d416514bae8784159b6b
Status: Downloaded newer image for sitespeedio/sitespeed.io:42.6.0
Google Chrome 151.0.7922.75 
Mozilla Firefox 153.0
Architecture: aarch64
[2026-09-09 10:30:36] INFO: Versions OS: linux 6.8.0-50-generic nodejs: v24.18.0 sitespeed.io: 42.6.0 browsertime: 28.3.0 coach: 9.2.1
[2026-09-09 10:30:37] INFO: Running tests using Chrome - 1 iteration(s)
[2026-09-09 10:30:38] INFO: Testing url http://host.docker.internal:8099/ iteration 1
[2026-09-09 10:30:47] INFO: Take after page complete check screenshot
[2026-09-09 10:30:47] INFO: Take cumulative layout shift screenshot
[2026-09-09 10:30:47] INFO: Take largest contentful paint screenshot
[2026-09-09 10:30:47] INFO: Start to measure route-one
[2026-09-09 10:31:01] INFO: Take after page complete check screenshot
[2026-09-09 10:31:01] INFO: Take cumulative layout shift screenshot
[2026-09-09 10:31:01] INFO: Take largest contentful paint screenshot
[2026-09-09 10:31:02] INFO: route-one: browsertime reports TBT=451 ms over 2 long tasks | correct per-route TBT=200 ms over 1 task(s) | document-wide sum=451 ms (longTask.navigationId present: true)
[2026-09-09 10:31:02] INFO: Start to measure route-two
[2026-09-09 10:31:16] INFO: Take after page complete check screenshot
[2026-09-09 10:31:16] INFO: Take cumulative layout shift screenshot
[2026-09-09 10:31:16] INFO: Take largest contentful paint screenshot
[2026-09-09 10:31:16] INFO: route-two: browsertime reports TBT=651 ms over 3 long tasks | correct per-route TBT=200 ms over 1 task(s) | document-wide sum=651 ms (longTask.navigationId present: true)
[2026-09-09 10:31:16] INFO: Start to measure route-three
[2026-09-09 10:31:30] INFO: Take after page complete check screenshot
[2026-09-09 10:31:30] INFO: Take cumulative layout shift screenshot
[2026-09-09 10:31:30] INFO: Take largest contentful paint screenshot
[2026-09-09 10:31:31] INFO: route-three: browsertime reports TBT=851 ms over 4 long tasks | correct per-route TBT=200 ms over 1 task(s) | document-wide sum=851 ms (longTask.navigationId present: true)
[2026-09-09 10:31:31] INFO: Start to measure route-four
[2026-09-09 10:31:44] INFO: Take after page complete check screenshot
[2026-09-09 10:31:45] INFO: Take cumulative layout shift screenshot
[2026-09-09 10:31:45] INFO: Take largest contentful paint screenshot
[2026-09-09 10:31:45] INFO: route-four: browsertime reports TBT=1051 ms over 5 long tasks | correct per-route TBT=200 ms over 1 task(s) | document-wide sum=1051 ms (longTask.navigationId present: true)
[2026-09-09 10:31:45] INFO: EXPECTED: every route blocks for the same 250 ms, so per-route TBT should be ~200 ms on each. ACTUAL: the reported value grows monotonically because it is the document-wide sum.
[2026-09-09 10:31:47] INFO: Get visual metrics from the video
[2026-09-09 10:31:49] INFO: Get visual metrics from the video
[2026-09-09 10:31:52] INFO: Get visual metrics from the video
[2026-09-09 10:31:55] INFO: Get visual metrics from the video
[2026-09-09 10:31:58] INFO: Get visual metrics from the video
[2026-09-09 10:32:01] INFO: http://host.docker.internal:8099/ 2 requests, TTFB: 16ms, firstPaint: 352ms, firstVisualChange: 363ms, FCP: 352ms, DOMContentLoaded: 332ms, LCP: 352ms, CLS: 0, TBT: 0ms, CPUBenchmark: 35ms, Load: 332ms, speedIndex: 363ms, visualComplete85: 363ms, lastVisualChange: 363ms
[2026-09-09 10:32:01] INFO: http://host.docker.internal:8099/one TTFB: 16ms, firstPaint: 352ms, firstVisualChange: 166ms, FCP: 22ms, DOMContentLoaded: 332ms, LCP: 22ms, CLS: 0, TBT: 451ms, CPUBenchmark: 34ms, Load: 332ms, speedIndex: 166ms, visualComplete85: 166ms, lastVisualChange: 166ms
[2026-09-09 10:32:01] INFO: http://host.docker.internal:8099/two TTFB: 16ms, firstPaint: 352ms, firstVisualChange: 179ms, FCP: 19ms, DOMContentLoaded: 332ms, LCP: 19ms, CLS: 0, TBT: 651ms, CPUBenchmark: 44ms, Load: 332ms, speedIndex: 179ms, visualComplete85: 179ms, lastVisualChange: 179ms
[2026-09-09 10:32:01] INFO: http://host.docker.internal:8099/three TTFB: 16ms, firstPaint: 352ms, firstVisualChange: 172ms, FCP: 19ms, DOMContentLoaded: 332ms, LCP: 19ms, CLS: 0, TBT: 851ms, CPUBenchmark: 35ms, Load: 332ms, speedIndex: 172ms, visualComplete85: 172ms, lastVisualChange: 172ms
[2026-09-09 10:32:01] INFO: http://host.docker.internal:8099/four TTFB: 16ms, firstPaint: 352ms, firstVisualChange: 143ms, FCP: 21ms, DOMContentLoaded: 332ms, LCP: 21ms, CLS: 0, TBT: 1.05s, CPUBenchmark: 35ms, Load: 332ms, speedIndex: 143ms, visualComplete85: 143ms, lastVisualChange: 143ms
[2026-09-09 10:32:01] INFO: The server responded with a 404 status code for http://host.docker.internal:8099/favicon.ico
[2026-09-09 10:32:01] ERROR: Could not generate coach data Error: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
    at Array.from (<anonymous>)
    at Object.convert (/usr/src/app/node_modules/pagexray/lib/index.js:74:27)
    at getPagesFromHar (file:///usr/src/app/node_modules/coach-core/lib/index.js:18:19)
    at analyseHar (file:///usr/src/app/node_modules/coach-core/lib/index.js:70:5)
    at async BrowsertimePlugin.processMessage (file:///usr/src/app/lib/plugins/browsertime/index.js:562:39)
[2026-09-09 10:32:01] INFO: The server responded with a 404 status code for http://host.docker.internal:8099/favicon.ico
[2026-09-09 10:32:01] ERROR: Could not generate coach data Error: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
    at Array.from (<anonymous>)
    at Object.convert (/usr/src/app/node_modules/pagexray/lib/index.js:74:27)
    at getPagesFromHar (file:///usr/src/app/node_modules/coach-core/lib/index.js:18:19)
    at analyseHar (file:///usr/src/app/node_modules/coach-core/lib/index.js:70:5)
    at async BrowsertimePlugin.processMessage (file:///usr/src/app/lib/plugins/browsertime/index.js:562:39)
[2026-09-09 10:32:01] INFO: The server responded with a 404 status code for http://host.docker.internal:8099/favicon.ico
[2026-09-09 10:32:01] ERROR: Could not generate coach data Error: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
    at Array.from (<anonymous>)
    at Object.convert (/usr/src/app/node_modules/pagexray/lib/index.js:74:27)
    at getPagesFromHar (file:///usr/src/app/node_modules/coach-core/lib/index.js:18:19)
    at analyseHar (file:///usr/src/app/node_modules/coach-core/lib/index.js:70:5)
    at async BrowsertimePlugin.processMessage (file:///usr/src/app/lib/plugins/browsertime/index.js:562:39)
[2026-09-09 10:32:01] INFO: The server responded with a 404 status code for http://host.docker.internal:8099/favicon.ico
[2026-09-09 10:32:01] ERROR: Could not generate coach data Error: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
TypeError: undefined is not iterable (cannot read property Symbol(Symbol.iterator))
    at Array.from (<anonymous>)
    at Object.convert (/usr/src/app/node_modules/pagexray/lib/index.js:74:27)
    at getPagesFromHar (file:///usr/src/app/node_modules/coach-core/lib/index.js:18:19)
    at analyseHar (file:///usr/src/app/node_modules/coach-core/lib/index.js:70:5)
    at async BrowsertimePlugin.processMessage (file:///usr/src/app/lib/plugins/browsertime/index.js:562:39)
[2026-09-09 10:32:01] INFO: The server responded with a 404 status code for http://host.docker.internal:8099/favicon.ico
[2026-09-09 10:32:02] INFO: HTML stored in /sitespeed.io/sitespeed-result/test_mjs/2026-09-09-10-30-36

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with lib/chrome/webdriver/chromium.js and lib/chrome/longTaskMetrics.js, then inspect browserscripts/timings/softNavigations.js for the existing CLS and INP navigation scoping. Reproduce the issue with docs/repro/soft-nav-tbt/test.mjs and its local HTTP server. Done means each soft-navigation route reports only its matching long tasks, with cumulative fields and affected buckets handled consistently.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript
Domain
performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.