From 343ea856633e7080c967862b08d4e8b9eb31babe Mon Sep 17 00:00:00 2001 From: Jane Chu <7559015+janechu@users.noreply.github.com> Date: Fri, 29 May 2026 14:21:56 -0700 Subject: [PATCH] docs: add SSR hydration troubleshooting guidance Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../declarative-templates/server-rendering.md | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/sites/website/src/docs/3.x/declarative-templates/server-rendering.md b/sites/website/src/docs/3.x/declarative-templates/server-rendering.md index 77921eba4fc..f4f247b59a0 100644 --- a/sites/website/src/docs/3.x/declarative-templates/server-rendering.md +++ b/sites/website/src/docs/3.x/declarative-templates/server-rendering.md @@ -298,6 +298,140 @@ fast build --attribute-name-strategy=none --templates="./components/**/*.html" The attribute name strategy must match between the server-side build and the client-side `attributeMap` configuration. If the build uses `--attribute-name-strategy=none`, import `attributeMap` from `@microsoft/fast-element/attribute-map.js` and configure the client with `attributeMap({ "attribute-name-strategy": "none" })`. Existing declarative imports remain supported. ::: +## Troubleshooting Hydration + +Hydration succeeds when the HTML produced by the server matches the template and +data that the client runtime sees during the element's first render. If hydration +does not run, FAST renders client-side. If hydration starts but cannot map a +binding, FAST reports a hydration error rather than silently repairing the DOM. + +### Call `enableHydration()` before elements connect + +Hydration is opt-in. Call `enableHydration()` before FAST elements are defined or +connected so the controller can install the hydration hook before the first +render. + +```ts +import { enableHydration } from "@microsoft/fast-element/hydration.js"; + +enableHydration(); +await import("./components.js"); +``` + +If a prerendered element connects before `enableHydration()` runs, the existing +shadow root is treated as client-render fallback: `isPrerendered` resolves +`true`, `isHydrated` resolves `false`, and FAST replaces the prerendered content +with a client-rendered view. Calling `enableHydration()` later does not hydrate +elements that already completed their first render. + +### Keep renderer and client versions in sync + +The renderer and client both rely on the same depth-first binding order and the +same marker syntax. Use matching FAST Element v3 versions of +`@microsoft/fast-build` and `@microsoft/fast-element`, and deploy server and +client updates together. Version skew can produce errors such as +`HydrationTargetElementError` or `HydrationBindingError` because the client +expects a different set or order of binding targets than the server emitted. + +### Check hydration markers + +FAST markers are intentionally data-free and sequential: + +| Marker | Purpose | +|---|---| +| `data-fe="N"` | `N` attribute, boolean, property, event, or directive bindings target the element | +| `...` | Content binding boundaries | +| `...` | One repeated item | +| `...` | Nested custom element boundary | + +Do not minify or sanitize away FAST comments or `data-fe` attributes before the +client loads. A missing `fe:/b` marker, an invalid `data-fe` count, or a changed +DOM shape means the hydration walker cannot target the compiled bindings. + +### Match the first repeat count + +Repeated views are hydrated by pairing existing `fe:r` ranges with the client's +initial array items by index. Ensure the server state and the client state have +the same item count and order for the first bind. + +```html + +
{{name}}
+