Skip to content

Fix blank Cart/Checkout templates and the flaky Lighthouse cart perf gate - #172

Merged
PAMulligan merged 3 commits into
mainfrom
fix/lighthouse-cart-perf
Oct 22, 2026
Merged

PAMulligan merged 3 commits into
mainfrom
fix/lighthouse-cart-perf

Conversation

@PAMulligan

Copy link
Copy Markdown
Collaborator

Summary

The lighthouse-ci check on #170 (Dependabot vite bump) failed /cart/ performance at 0.59 (runs 0.47 / 0.59 / 0.59), while the electron bump started 15 s later passed at 0.90 — on byte-identical pages. The bump didn't cause it; the theme's Cart and Checkout pages have never rendered anything, and that made the Lighthouse score a coin flip.

Root cause

page-cart.html / page-checkout.html embed a bare <!-- wp:woocommerce/cart /--> / <!-- wp:woocommerce/checkout /-->. Those blocks render only their inner-block tree, so with none declared the output is a stray </div>: /cart/ loads ~730 KB gz of Cart-block JS and shows nothing under "Your cart"; /checkout/ is blank.

A blank page has no images, so Chrome gives all 61 blocking scripts "High" priority. Whether Lantern treats them as render-blocking then depends on whether the runner happens to paint before executing them — simulated FCP 2.6 s (perf 0.90) vs 6.9 s (perf 0.59). The vite run landed on a slower runner and lost that race on all 3 runs.

Changes

  1. Templates — both now render the page's own content with <!-- wp:post-content /-->, like page-myaccount.html and WooCommerce's bundled page-cart/page-checkout templates. The content WooCommerce writes to those pages on install carries the full block trees. Empty cart, filled cart and the checkout form all render (checked in headless Chrome at 412 px and 1440 px — summary table under Verification).
  2. Perf floor — functional-page categories:performance in lighthouserc.json: 0.85 → 0.50. A working Cart block can't reach 0.85 under mobile simulation: it renders client-side, so its LCP element only paints after the WooCommerce/core JS has run — simulated LCP is ~7–8 s on every run. Over 15 local runs it scored 0.44–0.66. The old floor only passed because the page was empty. Script/CSS/image budgets, CLS, a11y and best-practices floors are unchanged and still pass.
  3. Workflow — include-hidden-files: true on the lighthouse-reports upload. upload-artifact@v4 skips dot-paths by default, so the artifact added in Lighthouse: raise a11y/SEO floors to 0.95 (closes #125) #161 has never contained anything (No files were found with the provided path: .lighthouseci/ on every run).
  4. setup-woocommerce.sh — stops creating missing Cart/Checkout pages with the same bare blocks; runs WooCommerce's own install_pages tool instead (a no-op when the pages exist).
  5. Docs — tests/lighthouse/README.md and CONTRIBUTING.md: the floor and its measurements, calibration history, and a correction: lhci asserts against the best of the 3 runs (default aggregationMethod: optimistic), not the median.

⚠️ Policy call for review: the 0.50 floor

0.50 is what a healthy cart scores under this suite, not a target. The alternative is to keep 0.85 and switch the cart to the classic [woocommerce_cart] shortcode (~6× less JS), which the docs already describe as a UX trade-off (#125). If you'd rather go that way, items 1, 3, 4 and 5 stand on their own.

Verification

Reproduced CI locally in an isolated Docker stack built from the same base image digest CI pulled (wordpress:php8.3-apache@sha256:f3e6835f…), WordPress 7.1.3, WooCommerce 11.2.1, Chrome 155, @lhci/cli 0.14 / Lighthouse 12.1 — the same versions as the failing run.

  • Broken cart (origin/main): 5 runs → 0.52, 0.83, 0.86, 0.76, 0.87 — the coin flip reproduces.
  • Fixed cart: 15 runs → 0.44–0.66, median 0.57; simulated LCP 7.1–8.1 s on every run; JS 734 KB (budget 800 KB).
  • Full suite (4 URLs × 3 runs) with this branch's config: lhci assert passes. Same runs against the old config: fails (cart best 0.63 < 0.85) — the template fix and the new floor have to ship together.
  • Deleted the Cart and Checkout pages and their woocommerce_*_page_id options, re-ran setup-woocommerce.sh --no-sample --theme flavian-shop --currency USD --country US:CA (the CI sidecar's args): both recreated with WooCommerce's block content and the page-cart / page-checkout template assignments.
  • validate-block-markup.sh, security-scan.sh, audit-tokens.sh pass on both templates; commitlint passes on both commits.
  • Not yet run in CI itself — this PR's lighthouse-ci check is that run.
Empty cart (mobile) Filled cart Checkout
renders "Your cart is currently empty" + product grid line item, coupons, total, Proceed to Checkout contact, billing, payment, order summary

After merge

  • chore(deps-dev): bump vite from 6.4.3 to 6.4.4 #170 needs a rebase onto main (@dependabot rebase) to pick this up; its own change is fine.
  • Visual-regression baselines for cart / checkout will change once tests/visual/baselines/ is bootstrapped (currently empty, so no diff runs).

Not addressed here

  • WooCommerce 11.2.1's cart page fetches /cart/undefinedwc/store/v1/cart (a malformed Store API URL, ~90 KB wasted per view) — WooCommerce bug, not ours.
  • Lighthouse 12.1 (via @lhci/cli 0.14) can't parse Chrome 155's traces for the largest-contentful-paint-element / layout-shifts audits (frame_sequence error). Bumping @lhci/cli would restore them; noted in the README's debugging section.

🤖 Generated with Claude Code

Paul Mulligan and others added 3 commits October 22, 2026 10:06
page-cart.html and page-checkout.html embedded a bare
<!-- wp:woocommerce/cart /--> / <!-- wp:woocommerce/checkout /-->. Those
blocks only render their inner-block tree, so with none declared the
cart page loaded the full Cart bundle (~730 KB gz) and showed nothing
under the heading, and the checkout page was blank.

Both templates now render the page's own content via wp:post-content,
as WooCommerce's bundled page-cart/page-checkout templates do; the
content WooCommerce writes to those pages on install carries the full
block trees.

setup-woocommerce.sh created the pages with the same bare blocks when
they were missing. It now runs WooCommerce's own install_pages tool
(a no-op when the pages exist) and leaves the Cart/Checkout content to
WooCommerce. Verified against WooCommerce 11.2.1 / WordPress 7.1.3:
deleting both pages and re-running the script recreates them with the
block trees and the page-cart/page-checkout template assignments.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The functional-page categories:performance floor drops from 0.85 to
0.50. The old floor only passed because /cart/ rendered no cart (see the
previous commit): the empty page had no images, so all 61 blocking
scripts got Chrome's "High" priority, and whether Lantern counted them
as render-blocking depended on whether the runner painted before
executing them -- simulated FCP 2.6 s (perf 0.90) or 6.9 s (perf 0.59)
on byte-identical pages. That coin-flip is what failed the Dependabot
vite bump (#170) on all three runs.

A working Cart block cannot reach 0.85: it renders client-side, so its
LCP element only paints after the WooCommerce/core JS has run, and
simulated LCP is ~7-8 s on every run (observed 0.44-0.66 over 15 local
runs; lhci asserts the best of the 3 runs). The resource budgets, CLS,
a11y and best-practices floors are unchanged and still gate the cart.

Also set include-hidden-files on the lighthouse-reports artifact upload:
upload-artifact@v4 skips dot-paths by default, so .lighthouseci/ was
never uploaded ("No files were found") since the step landed in #161.

Docs: describe the floor and its measurements, correct the claim that
assertions evaluate the median run (lhci's default aggregationMethod is
optimistic), and add the calibration-history entry.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@PAMulligan
PAMulligan merged commit 95e7a74 into main Oct 22, 2026
19 checks passed
@PAMulligan
PAMulligan deleted the fix/lighthouse-cart-perf branch October 22, 2026 17:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant