08 Sept 2026 · 4 min read
Hyva performance hardening: CSP, FPC, and measurement
The performance work that follows a Hyva migration — consolidating CSP, using Hyva base-layout resets, keeping full-page cache correct, and measuring the before/after so the gains are provable.
Part 13 of the Hyva series — the final post. Implementation-focused, drawn from real hardening passes (project names withheld).
Hyva already won most of the battle
The headline performance gain — dropping Knockout, RequireJS, and customer-data polling — lands the moment the theme renders. Catalog and product pages ship a fraction of the JavaScript Luma did, and Core Web Vitals move accordingly. The work in this post is the hardening that makes those gains stable and measurable, not the initial win.
Consolidating CSP
Because Hyva changes how scripts and styles load (one JS file, one CSS file, Alpine components instead of a requirejs graph), the Content Security Policy from a Luma setup is usually both too strict and too loose. Migrations tend to converge on Hyva's built-in CSP handling and retire a bespoke CSP plugin that was patching Luma's gaps.
The concrete cleanup observed:
- Remove the custom CSP extension once Hyva's CSP covers the storefront.
- Audit the remaining directives against the actual console output on key pages (home, category, product, checkout). The main menu and the cart are the usual sources of a missing directive.
- Fix coupon-code and similar small widgets that loaded a script the new CSP blocked.
Measure CSP by opening the browser console on each key route after the theme switch — every violation is a visible red line, and the goal is zero on the pages customers land on.
Using Hyva base-layout resets
Hyva ships generated base-layout resets that normalize the document so Tailwind's preflight behaves consistently. A common misstep is overriding these with an older Hyva/reset theme, which leaves conflicting rules. The migrations that stayed clean used the generated base layout resets from the current Hyva base rather than carrying forward a legacy reset theme. If you see surprising spacing or box-model drift after upgrade, check which reset layer is winning.
Full-page cache and JavaScript dependencies
FPC is your ally on every route except where dynamic JS must be present. Two rules keep it correct:
- Exclude or hole-punch the checkout. The checkout's React/Magewire fragments must not be served as a static cached page (see the checkout post for the failure mode where the cached HTML missed a script the React app needed).
- Verify the cached catalog is complete. After enabling FPC, fetch a category page twice and confirm the second response is a cache hit and still loads its single JS file. A misconfigured cache that strips the script tag breaks interactivity while looking fast.
A quick check: curl -I the page, confirm Age/CF-Cache-Status (or your cache header) shows a hit, then load it in a browser and confirm the minicart and layered nav still work.
Measuring before and after
The gains are only real if you can show them. Capture, on the Luma pages and again on Hyva:
- Lighthouse performance score on category and product.
- Total JavaScript transferred (the metric Hyva moves the most).
- Server timing / TTFB on a warm cache.
- A WebPageTest or equivalent filmstrip for the largest contentful paint.
Govard's audit workflow can capture server-side timing and query cost on a throwaway environment, and the maestro-skills review and audit skills help keep each performance change reviewed as it lands. The before/after pair is also your rollback justification: if a later change regresses the numbers, you have a baseline to compare against.
A hardening checklist
- CSP consolidated to Hyva's built-in handling; zero console violations on key pages.
- Base-layout resets from the current Hyva base, no legacy reset theme.
- FPC verified on catalog; checkout correctly excluded or hole-punched.
- Before/after Lighthouse + transfer-size captured and stored.
- A regression baseline so future changes are measured against it.
Closing the series
This series went from the decision (what Hyva is, when it fits, when it does not) through building the core storefront (theme, layout, Alpine, view models, compatibility, migration) to the advanced edges (Checkout, React, performance). The throughline: Hyva is a predictable, bounded rebuild of the presentation layer — the risk is in the third-party compatibility and the checkout, not in the architecture. Plan those, measure the result, and the migration is routine rather than heroic.
This was the final post in the Hyva series.