Server rendering and hydration
Grona changes your page in the visitor’s browser, after your HTML arrives. If your framework renders or re-renders the same elements on the client, through hydration or a later update, the two can collide. This page explains how they interact and how to set up your pages so changes stick.
How Grona and your framework share the page
Section titled “How Grona and your framework share the page”- Your server sends HTML. The anti-flicker script hides
<body>. main.jsloads, picks the visitor’s variation and downloads its changes.- Grona waits for the DOM to be ready, then applies the changes to the elements in it and reveals the page.
- Your framework’s own scripts hydrate or render the page, and keep updating it as state changes.
Grona does not coordinate with step 4. It has no hook for hydration, and there is no API to tell Grona that your app has finished rendering or to ask it to apply changes again.
What happens when the framework touches a changed element
Section titled “What happens when the framework touches a changed element”- The element is replaced or redrawn after Grona changed it. The change is lost for that page view. Grona does not re-apply it.
- The element does not exist yet when Grona runs. Grona watches the page and applies the change when the element appears, for up to 20 seconds without progress. After that it stops watching.
- The element is a React or Vue node with children. A text change on it is skipped and reported as failed, because replacing children that the framework controls would crash the app on its next update. Other frameworks are not detected, so this guard does not protect Angular, Svelte or similar apps.
- The element moved. Grona finds an element by its position in the page, or by its attributes, text or a nearby landmark where the change recorded them. If your markup changes so that none of these match, the change silently does nothing.
Set up your pages so changes stick
Section titled “Set up your pages so changes stick”- Render the content you want to change on the server. Content that is in the server HTML is in the DOM when Grona applies its changes. Content rendered only on the client depends on the 20 second watcher.
- Keep the markup stable between the server render and hydration. If hydration replaces an element rather than reusing it, Grona’s change on it is lost.
- Give important elements stable attributes. A fixed
id, or a test attribute such asdata-testid,data-test,data-qaordata-cy, gives Grona something to find that does not depend on the element’s position. Generated values, such as React’s:r1:ids, are ignored. - Put the snippet in the server-rendered
<head>. Write the three tags into your HTML template or root layout as plain tags. A framework script loader, such as Next.jsnext/script, loads them asynchronously, and the anti-flicker script can no longer hide the first paint. See Prevent flicker.
Next steps
Section titled “Next steps”- Single-page applications, for client-side route changes, where Grona re-runs campaigns on each new route
- Custom sites and frameworks