Releases: sitespeedio/browsertime
Releases · sitespeedio/browsertime
v27.5.0
Added
- Bumped
chromedriverandedgedriverto 149 #2487. - Updated the Docker image to Chrome 149 / Firefox 151 / Edge 149 #2486 #2488.
Fixed
- Navigation-script failures now include the URL being tested and the iteration number in the error message, so failure logs and
markAsFailureoutput point at the offending page without cross-referencing the surrounding log lines #2489.
v27.4.1
v27.4.0
Added
- JS/CSS coverage collection for Chrome.
--chrome.coverageturns it on for every iteration for users who want the data and accept that detailed V8 coverage deoptimizes scripts and will skew their timing metrics.--enableProfileRunalso turns coverage on for Chrome alongside the existing trace, so users who want coverage without affecting their timings can lean on the same extra-iteration pattern they already use for tracing — the result is merged back into the mainbrowsertime.jsonso consumers like sitespeed.io see the data in the same place they read every other metric. Each entry has a per-file breakdown (url,totalBytes,usedBytes,unusedBytes,unusedPercent) #2480.
Fixed
- HAR post-processing no longer throws when a page has no matching entries. Occasionally a HAR contains a page whose
pagerefhas no entries — typically a navigation that didn't produce any requests, or an extension-injected page.getDocumentRequestsandgetFinalURLdereferencedshift()/pop()without a guard, andgetMainDocumentTimingswrapped its entire per-page loop in a single try/catch so one bad page wiped out the main-document timings for every other page in the same HAR. Downstream this surfaced as a noisy triplet of warnings followed by an empty coach-data payload in sitespeed.io. The three crash points are now guarded and unresolvable pages are skipped #2483. - Bumped
geckodriverto a version with native ARM-64 support #2482.
v27.3.0
Added
browsertime --helpis now navigable by topic. The default view shows a short curated list of common options plus the available topic names.browsertime --help <topic>shows just that topic, andbrowsertime --help-allreproduces the historical full dump for scripts and power users. The old single-screen dump of every option from all 13 topic groups was overwhelming for new users and slow to skim; the topic-filtered view follows the curl/ffmpeg pattern #2467.
Fixed
- TypeScript types and IntelliSense for navigation scripts are tightened across the script-facing surface. A new
BrowsertimeScripttype alias lets scripts annotate their default export and get bothcontextandcommandstyped in one line. The high-level command helpers (navigate,find,getText,fill,hover,press,getTitle,waitForUrl, …) now surface their JSDoc parameter and return types in IntelliSense instead of being typed asFunction, andcommands.findresolves to a realWebElementso chained calls get completion from selenium-webdriver #2476.context.options,context.result, andcontext.taskDataare typed asRecord<string, any>so editors offer completion oncontext.options.etc. #2478.commands.mouseis now a proper shape (selector typed asstring,singleClick's options surfacewaitForNavigation) instead of an anonymous object literal, andmeasure.stop/measure.clickAndMeasure/measure.stopAsErrorreturn types are explicit (Promise<void>/Promise<unknown>) instead ofPromise<any>#2479. - How Browsertime publishes its TypeScript types is now safer.
scripting.d.tsmoved to the repo root next topackage.jsonso it can't be clobbered by a futuretscoutDir change, thetypescondition comes first underexportsto match TypeScript's documented resolution rules, andpublintruns as part ofprepublishOnlyso common package.json mistakes fail before a release goes out #2477. - Replaced the direct
lodash.mergedependency with a small in-treemerge()helper inlib/support/util.js. The helper matches lodash's actual semantics for the cases Browsertime relies on — arrays merged by index,undefinedsource values skipped unless the key is missing on the target,Date/RegExp/class instances passed by reference, prototype-pollution keys rejected — which finishes the lodash unbundling the same way sitespeed.io did #2468. - Bumped dependencies:
chrome-har1.3.1 #2469,chrome-remote-interfaceandselenium-webdriver#2475,@sitespeed.io/log2.0 #2471,chromedriver/edgedriver/geckodriver#2472.
v27.2.0
Added
- Surface the page-level
recalculateStylesummary (beforeFCP / beforeLCP element counts + durations) on the first HAR page as_renderBlocking.recalculateStyle. The per-request_renderBlockingmap already projected onto each entry stays where it is — the page-level summary is what powers the "Elements that needed recalculate style before FCP" view and was previously only reachable viabrowsertime.json#2466.
v27.1.0
Added
- Three new analyses on
result.cpuderived from the same Chrometrace.jsonthat's already collected when--cpuis on.scriptCostsproduces the per-URL parse / compile / execute / total breakdown that Lighthouse's bootup-time audit shows, sorted by total descending.forcedReflowswalks the main-thread task tree forLayout/UpdateLayoutTreeevents nested inside JS-driven tasks (EventDispatch,FunctionCall,TimerFire,FireAnimationFrame, …) — every match is a synchronous reflow caused by JavaScript reading a layout-triggering property mid-handler, reported with the script that triggered it.nonCompositedAnimationssurfacesAnimationevents whosecompositeFailedbitmask is non-zero, returning the unsupported properties (top,box-shadow,filter, …) so consumers can see what to swap for the GPU-friendly equivalent. Each new analysis is wrapped in its own try / catch so a bug in one can't poison the existingcategories/events/urlspayload
Fixed
- Replace the unmaintained
@sitespeed.io/traciumdependency (extracted from Lighthouse circa 2017, last release 0.3.3) with an in-tree ESM port atlib/chrome/trace/. The algorithm is a 1:1 port; output ofcomputeMainThreadTasksis byte-equivalent for any trace, so existingresult.cpu.{categories,events,urls}consumers see no change. Pulling the parser inline lets new analyses ship at Browsertime's release cadence without a secondnpm publishstep in between - Modernise the trace-event classifier. The original list only knew about ~30 event names, so on busy 2026-era pages roughly half the trace fell through to "other" — on a sample cnet run that meant 1.3 s of "other" hiding
RunTask,v8.run,IntersectionObserverController::computeIntersections,PrePaint,Commit,Layerize,v8.callFunction,V8.DeserializeContextand friends. The expanded list draws from modern Lighthouse + the WebPageTest-derived map in waterfall-tools + direct sampling of real traces, and a newgroupForEvent()lookup addsV8.GC*prefix matching so future V8 GC phases auto-classify - Bump
chrome-harto 1.3.0 to pick up the new_renderBlockingfield on each entry, lifting Chrome's CDPrenderBlockingStatus(Chrome 108+) so downstream HAR consumers can see which resources blocked first paint without inferring it from the trace.
v27.0.4
v27.0.3
v27.0.2
Fixed
- SPA scripts no longer drop a HAR page when Chrome's soft-navigation
PerformanceObserverentry doesn't fire. #2438 gated HAR-page creation on Chrome detecting all three soft-navigation criteria (interaction + URL change + visible paint within a short window), but real SPAs like Grafana sometimes paint too late and Chrome never emits the entry — chrome-har then sees onlyNetwork.*events for that measurement and emits zero pages, breaking downstream per-iteration page indexing in sitespeed.io. When the measurement was started without a URL (commands.measure.start(alias)form) and no soft-nav entry was detected, fall back to a synthetic page anchored at the currentlocation.hrefso eachmeasure.startproduces exactly one HAR page.
v27.0.1
Fixed
commands.clicknow falls back to a JavaScript click when the Actions API can't reach the element. Hidden elements have a zero-size bounding box, so the Actions API click that became the default in #2381 silently moved the pointer to (0,0) and clicked nothing instead of triggering the handler. The click command now pre-checksisDisplayed()and uses a JS click when the element isn't displayed, and otherwise catches any Actions API failure and retries with a JS click. Each fallback is logged at info level so it's visible without--verbose. Restores the documented "hide everything before clicking" pattern used by visual-metric scripts #2452.engineDelegate.afterBrowserStopped()is no longer called twice per iteration on the happy path. #2432 added a safety-net cleanup call in the iterationfinallyblock so failure paths still release long-lived helpers, but in the happy path_stopBrowserhad already invoked the cleanup, so it ran twice. The visible symptom on Chrome was a spuriousENOENTerror from the secondcleanUserDataDir(the first call had already removed the directory). It could also double-terminate the iOS simulator's Safari and theios-captureserver. The safety-net now runs only when_stopBrowserdidn't already reach the cleanup #2453.cleanUserDataDircleanup now usesrm(..., { recursive: true, force: true })so a missing directory is treated as already-cleaned. Defense in depth alongside #2453: if anything in the future double-calls the Chrome cleanup, or if Chrome failed to create the directory in the first place, the cleanup stays quiet instead of logging a spuriousENOENT#2454.