Hydration Validation
Hydration validation must follow the route policy. A default full route and a hydration: "none" route are both valid, but their expected browser signals are intentionally different.
Run the right check
Using the two article routes from Hydration as a comparison, run these commands in the root of an application with frontend and SSR enabled:
Open /article/interactive/intro and /article/intro directly and check the full/none conditions below. Both original HTML responses should contain the article body and SEO title. The interactive route's button should increment its count; the other stays at Clicks: 0. Native GET forms and links should work in both. Inspect Console, Network, Elements, and Performance in browser developer tools; the final page merely appearing is not enough. Stop the service afterward.
The full-route checks below assume completed SSR. SSR-disabled, clientOnly, and client-fallback shells use createRoot; see CSR mounting. Both modes should have working interactions and no hydration errors.
Default full route
A production smoke for the default policy should check:
- the page returns SSR HTML
- JS, CSS, and other assets return 2xx
- there are no browser console or page errors
- route-specific
modulepreloadexists - the marker reaches
data-vext-hydration="done" - a Performance entry named
vext:hydrationexists size-report.jsonin the build output contains route metrics when bothfrontend.build.diagnostics.sizeReportandperformanceReportare enabled; the latter alone does not guarantee that file
hydration: "none" route
A none page should instead check:
- the page still returns SSR HTML, CSS, and SEO metadata
- the root is marked
data-vext-hydration="none" - no Vext browser entry,
__VEXT_DATA__, ordata-vext-route-preloadis emitted - normal
<a>links and normal HTML<form>elements use normal document navigation or submission - the test does not expect the
donemarker, thevext:hydrationPerformance entry, React events, Vext Form enhancement, fetcher, or framework-managed client navigation; the native form rendered by Vext Form still follows its action/method
Runtime Signals
Expected client-side signals for the default policy:
For hydration: "none", the intentional signal is:
These are intended for tests and diagnostics. They should stay quiet in production logs.
done means the root boundary's effect ran; a Performance entry also requires the browser Performance API. Neither replaces error and actual-interaction checks or proves all asynchronous content finished.
Common Failures
When Maintaining This Repository's Docs
Run npm run verify:docs-contract in the framework repository to check the documentation contract. It does not start an application or prove browser behavior. Application readers use the build/start and browser flow above, without a repository-internal consumer command.