Skip to content

Frontend: No performance budget: 349 kB of shared JavaScript loads before anything renders #506

Description

@Emmy123222

Goal this serves — Donors on slow connections completing donations

Why this matters

Every page loads 349 kB of shared JavaScript before rendering. On a fast connection that is invisible; on a mid-range phone over mobile data — which is how a large share of donors worldwide browse — it is many seconds of blank screen before a project page is usable.

For a platform whose purpose is collecting donations, that delay sits directly in front of the conversion step. Nothing currently measures it, so it can regress indefinitely without anyone noticing.

Evidence

First Load JS shared by all              349 kB
  chunks/pages/_app-*.js                 258 kB

The application shell alone is 258 kB. Contributing factors are visible in the dependency set: the full Stellar SDK, a charting library, a 3D rendering library for the network graph, and an internationalisation message formatter — several of which are needed on a small number of routes but are paid for on all of them.

No budget is enforced anywhere in CI, and no Core Web Vitals measurement exists.

Why this is hard

The heavy dependencies are load-bearing. The Stellar SDK is required to build and sign transactions, and cannot simply be dropped — it has to be deferred to the point of use without breaking the donation flow or reintroducing a delay at the worst moment.

Server-side rendering is mandatory here. _app.tsx forces it so the CSP nonce reaches every script, which constrains which optimisations are available.

Budgets need enforcement to matter. A measured number that does not fail a build regresses within weeks.

Field data differs from lab data. Synthetic measurements miss what real donors experience, and the metric that matters — whether donations complete — is not a bundle size.

Suggested approach

Establish budgets per route and enforce them in CI so a regression fails the build with a clear diff of what grew.

Defer route-specific heavy dependencies to their point of use, taking particular care that the donation flow does not simply move its delay to the moment of signing.

Measure Core Web Vitals in the field rather than only in the lab, and connect the result to donation completion so the work is justified by outcome rather than by a number going down.

Acceptance criteria

  • Per-route performance budgets are enforced in CI; exceeding one fails the build with a readable diff.
  • Shared first-load JavaScript is materially reduced, with before and after figures recorded.
  • Route-specific heavy dependencies load at point of use without introducing a delay inside the donation flow.
  • The donation path is measured end to end and does not regress; this is asserted by a test.
  • Core Web Vitals are collected from real sessions, not only synthetic runs.
  • Server-side rendering and the nonce-based CSP continue to work unchanged.
  • Donation completion rate is reported alongside performance metrics so impact is visible.
  • A short guide explains how to add a dependency without breaking the budget.

Scope

Roughly 5,000–7,000 lines, including tests.

Relevant files

  • frontend/next.config.mjs
  • frontend/pages/_app.tsx
  • frontend/components/TransactionGraphVisualizer.tsx
  • frontend/lib/stellar.ts
  • .github/workflows/ci.yml

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: frontendNext.js web appcomplexity: highSubstantial design/implementation work, not a quick fix

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions