perf: fix slow page loads and gate performance in CI

- Ship one hashed Tailwind stylesheet instead of two (one render-blocking)
- Compress responses in-app (brotli/gzip, streaming-safe) and precompress
  the node build so local and CI measurements match production
- Validate the Supabase session once per request
- Render the homepage immediately and stream public stats
- Stream a Pokedex's entries with the page instead of fetching after
  hydration, running the rows and count queries in parallel
- Shrink the avatar and offline placeholder images, fix layout shift,
  contrast, link names and missing meta descriptions
- Add Lighthouse CI (mobile + desktop) with score and metric budgets,
  bundle-size budgets in the build tests, and signed-in speed scenarios
This commit is contained in:
Josh Creek
2026-09-14 20:53:53 +01:00
parent 556f120f16
commit ff29095c47
30 changed files with 4166 additions and 487 deletions
+11 -1
View File
@@ -40,7 +40,17 @@ The test suite is split by responsibility so a failure points to the correct lay
- `tests/integration` checks the migrated Supabase schema, views, constraints, RLS, and repositories.
- `tests/bdd/features` is the executable Gherkin specification for user-visible behaviour. Step
definitions and browser fixtures live beside it under `tests/bdd`.
- `tests/build` verifies generated service-worker and manifest artifacts after each supported build.
- `tests/build` verifies generated service-worker and manifest artifacts after each supported build,
and fails if the gzipped JS or CSS every page loads grows past its budget.
- `lighthouserc.cjs` audits the public pages with Lighthouse CI (`npm run test:lighthouse`, which
builds and serves the Node output). PRs fail if Performance, Accessibility, Best Practices or SEO
drops below 90, or if LCP, TBT, CLS, script, stylesheet or total transfer size exceeds its budget.
CI runs it with both the mobile and desktop profiles (`LHCI_PRESET=desktop`).
- `tests/bdd/features/performance.feature` holds time budgets for signed-in pages Lighthouse can't
reach: opening a Pokédex and switching between it and the Pokédex list.
The budgets sit just above current measurements so regressions fail the PR. If a change genuinely
needs more, raise the budget in the same PR so the cost is reviewed.
Run the offline suites while developing. `test:fast` includes the coverage run, so there is no need
to run both: