Skip to content

Releases: sitespeedio/sitespeed.io

41.3.3

09 Jun 14:24

Choose a tag to compare

What's Changed

  • Chain downstream release workflows via workflow_dispatch by @soulgalore in #4786

Full Changelog: v41.3.2...v41.3.3

41.3.2

09 Jun 10:03

Choose a tag to compare

What's Changed

Full Changelog: v41.3.1...v41.3.2

41.3.1

09 Jun 08:41

Choose a tag to compare

What's Changed

Full Changelog: v41.3.0...v41.3.1

v41.3.0

07 Jun 14:11

Choose a tag to compare

Added

  • Docker base image bumped browsers to chrome-149.0-firefox-151.0-edge-149.0 #4774, #4775.

Fixed

  • Browsertime 27.5.0 #4776.

v41.2.1

31 May 12:31

Choose a tag to compare

Fixed

  • Unblock the arm64 Docker release build by bumping the QEMU binfmt emulator to a 9.2 build that handles modern systemd, and pinning APT so only the Firefox package is pulled from Debian unstable #4771.
  • Move the slim Docker image to Debian trixie (the new stable) and drop the APT pin from #4771, which was too strict to let Firefox's libc6 / libnss3 dependencies upgrade from unstable #4772.
  • CI: allow Docker Hub's CloudFront CDN (production.cloudfront.docker.com) through the Linux workflow's Harden-Runner egress allowlist, so the test job stops flaking when DNS routes the runner to CloudFront instead of Cloudflare #4773.

v41.2.0

27 May 12:43

Choose a tag to compare

Added

  • JS/CSS coverage in the report. Browsertime 27.4.0 collects per-iteration coverage when you pass --chrome.coverage, and the HTML report now surfaces it as a Coverage section in the per-URL view: median JS/CSS total/unused/percent KPIs, first-party vs third-party split, top-25 worst-offender tables, and a methodology + recommendations panel. --chrome.coverage is declared in sitespeed.io's own CLI so it shows up in --help and the config reference, and the --enableProfileRun path now collects coverage on the profile run and merges it into the main result #4769, #4767.

Fixed

  • Visual-change lines (_firstVisualChange / _lastVisualChange / _visualComplete85) are back on the waterfall when the HAR is gzipped on disk (the default). The renderer's user-timing injection was parsing the raw gzip bytes as JSON and silently falling back to the unannotated HAR; it now sniffs the gzip magic bytes and inflates via DecompressionStream first #4758.
  • Per-request detail panel on the waterfall now shows real data again. The panel was reading HAR-shape fields (req.response.content.size, req.response.headers, req.response.status, req.timings, …) but waterfall-tools' click payload is its own flat internal Request object, so Response body always showed 0 B, Status was blank, MIME type and Protocol were , and the response-headers and timing tabs were empty. Look up the matching HAR entry by index and read the rich HAR shape from it, falling back to the waterfall-tools shape only when the HAR is missing.
  • Folder path aliases now accept Unicode letters and digits, so non-ASCII URLs no longer collapse to - in result paths (issue #3880) #4759.
  • scp plugin: retry the initial SFTP handshake up to 3× with linear backoff. ssh2-sftp-client v12 removed its built-in connect retries, so a single "Connection lost before handshake" blip was failing the whole upload #4760.
  • Graphite: retry the post-run annotation POST up to 3× on network errors and 5xx responses. 4xx still fails fast #4761
  • waterfall-tools bumped to the first proper npm release, 0.3.0 — no more pinning to a GitHub tarball, and the bundling script drops to ~30 fewer lines now that the published browser bundle has the platform aliases baked in #4764.
  • Browsertime 27.4.0 #4767.
  • Docker base image rev'd to chrome-148.0-firefox-150.0-edge-147.0-d #4762.
  • Slim Docker image cleanup #4757.
  • Drop now-unused npm overrides from package.json #4756.
  • CI: PR Docker workflow now builds and exercises the image on arm64 in addition to amd64, so arch-specific breakage surfaces pre-merge instead of at release-tag time. Edge step is skipped on arm64 (Linux Edge is amd64-only) #4766.
  • CI: pin the Safari workflow to macos-14 #4765.
  • Drop an unnecessary \. escape inside a character class in pathToFolder that was tripping eslint's no-useless-escape and failing lint on every PR #4763.
  • Docs: remove unused CSS #4768.

v41.1.0

20 May 19:18

Choose a tag to compare

Added

  • New rsync plugin for result uploads. The existing scp plugin walks files one at a time over a single SFTP channel, which is the worst case for a result directory of thousands of small files. The new plugin shells out to rsync over ssh, pipelines the wire protocol and reuses the channel — the same upload finishes in a small fraction of the time on a typical Linux host. Exposed as --rsync.host / --rsync.username / --rsync.privateKey / --rsync.destinationPath etc., sitting alongside scp, s3 and gcs; existing scp users keep their exact behaviour and opt in to rsync only when they want it #4739.
  • Upload performance on the existing scp plugin: swapped node-scp (serial uploads, stuck on 0.0.25) for ssh2-sftp-client, which fans out 16 concurrent uploads on the same ssh2 transport. Same auth, same options, same CLI surface — just faster on result directories with many small files #4738.

Fixed

  • Bring back the visual-change markers on the waterfall. The renderer that replaced PerfCascade in #4614 only drew vertical lines for a fixed set of page-event names, so the _firstVisualChange / _lastVisualChange / _visualComplete85 lines silently disappeared with the swap. They're now hoisted into the user-timing-marks bag the renderer does draw, the "Marks & visual metrics" toggle is on by default, and the hover tooltip identifies which metric or user mark the cursor is on #4755.
  • Browsertime 27.3.0 #4754.
  • coach-core bumped to 9.2.1 #4750.
  • Bump @sitespeed.io/log and the bundled plugin to latest #4746.
  • Crawler rewrite: simplecrawler (unmaintained since 2020, ~1000 lines of transitive code) is replaced by an in-tree node:fetch-based crawler in ~285 lines with no new dependency. Same BFS semantics, same depth/maxPages/include/exclude/content-type/skip-extension rules, same robots.txt handling (--crawler.ignoreRobotsTxt still opts out), same cookies/basicAuth/userAgent passthrough. Parity verified across four real-site runs at different depths and page caps; natural completion is ~6× faster on the sample runs #4745.
  • Dependency pruning, no behaviour change for users: lodash.get, lodash.set and lodash.merge are replaced by small in-tree helpers in lib/support/objectPath.js, with the merge replacement verified byte-for-byte against lodash.merge across 23 edge cases and an A/B parseCommandLine() run. dayjs (plus the utc plugin) is replaced by an ~80-line lib/support/time.js, with every .format() pattern actually used in the codebase pinned in a new test. ora is replaced by a ~60-line blinking-dot spinner used only by --api.add / --api.addAndGetResult. The lodash subtree is now gone entirely [#4737, #4741, #4742, #4744, #4740].
  • The markdown template helper exposed to pug templates is removed. It was added in 2018 (#2161) but no shipped .pug template has ever called it, and the underlying markdown@0.5.0 package has been unmaintained for over a decade with an open ReDoS advisory. Anyone with a custom pug template that calls markdown(...) will need to import their own renderer #4743.
  • Slimmer main Docker image: apt-get install --no-install-recommends + /var/lib/apt/lists cleanup, npm ci (lockfile-strict) instead of npm install, and the selenium-webdriver/bin cleanup folded into the install layer so the deleted bytes no longer ship in an earlier layer #4753.
  • Docker: use --omit=dev instead of the deprecated --production, and fix the skip edgedriver typo #4752.
  • Release tooling: bump feed to 5.2.1 and marked to 18.0.3 (used only by release/feed.js when refreshing documentation RSS feeds). API usage unchanged, regenerated feeds are content-identical #4751.
  • Dev tooling: align with eslint 10 and unicorn 64, drop the dead legacy .eslintrc.json and the stale eslint-check script, minor bumps to prettier/sass/esbuild #4747.

v41.0.1

16 May 05:12

Choose a tag to compare

Fixed

  • Drop unused fast-crc32c dependency #4735
  • Fix visual-progress curve and scrubber to match the data's semantics
    #4734

v41.0.0

15 May 04:20

Choose a tag to compare

Highlights

A small but breaking release: Node.js 22 is now the minimum, and --help has been redesigned around topic-filtered views instead of dumping every option in one screen.

Breaking

  • Node.js 22+ is now required (was Node.js 20+) #4732.
  • sitespeed.io --help no longer prints every option from all 26 option groups by default — it now shows a short curated list of common options plus the available topic names. Use sitespeed.io --help <topic> to drill into one topic, or sitespeed.io --help-all to reproduce the historical full dump (kept unchanged for scripts, and used to generate the published docs/config reference) #4730.

Changed

  • coach-core bumped to 9.1.0, which pulls in pagexray 5.0.0 #4731.

Fixed

pagexray 5.0.0 (transitive via coach-core 9.1.0) brings several reporting fixes that show up directly in sitespeed.io output:

  • HTTP/3 / HTTP/3.0 connections are now classified as h3 instead of falling through to h1, so the HTTP-version breakdown is correct on HTTP/3 traffic.
  • Cache-Control is parsed case-insensitively (RFC 7234), so Max-Age=42 is read as 42 instead of 0 and No-Cache / No-Store are honoured — caching advice and expireStats no longer over-report problems on origins that capitalise the directive.
  • missingCompression no longer flags already-gzipped assets (the encoding check was comparing a flattened header array against a string), accepts compound encodings like br, gzip, and recognises zstd. xml is now also considered for compression reporting.
  • The Domain= cookie attribute is matched case-insensitively (RFC 6265), so third-party cookies set with lowercase domain= are detected.
  • getMainDomain recognises common two-label public suffixes (.co.jp, .com.br, .com.au, …), so the auto-generated first-party regex stops misclassifying same-site requests on non-.co.uk country domains.
  • defaultContentTypes now includes favicon, so every page has a consistent shape in the content-type breakdown.
  • getDocumentRequests returns an empty array for pages with no matching entries instead of throwing.

v40.5.0

14 May 13:21

Choose a tag to compare

Added

  • Scripts are now auto-detected on the command line, so --multi is no longer required to run them. Any positional argument that looks like a script — .js / .cjs / .mjs, or any file whose first non-empty line doesn't start with http — flips multi mode on automatically, and mixed inputs like login.js https://example.com logout.js just work. --multi is kept as an explicit override for the one case auto-detection can't cover: sharing a single browser session across a list of plain URLs. All existing invocations behave exactly as before #4725.

Fixed

  • Gzipped HAR files are now written by piping JSON through createGzip straight to disk instead of materialising the JSON string, a Buffer copy of it, and the full gzipped Buffer all at once. For a 200 MB HAR that removes several hundred MB of avoidable peak RSS, multiplied when multiple pages finish around the same time. The storage layer now accepts a Readable in addition to strings and Buffers; existing callers are unaffected #4728.
  • Gzipped JSON result files (Chrome traces, console logs, etc.) are read by streaming through createGunzip and collecting utf-8 chunks rather than buffering the whole gzipped payload, gunzipping it into another Buffer, then stringifying. The parsed object still has to fit in memory, but the throwaway gzipped and unzipped buffer copies are gone — meaningful on 50+ MB traces #4726.
  • The sustainable plugin and the S3 plugin pick up the same streaming treatment: the sustainable plugin now uses the shared streaming gzipped-JSON helper instead of its own buffer-everything copy, and the S3 plugin streams uploads via createReadStream with an explicit ContentLength instead of loading each file fully into memory before PutObject. With 20 concurrent S3 uploads, RSS no longer spikes to ~20× the size of the largest file in the result bundle #4727.