Working demos of the Interactivity API renderHTML() function proposed in WordPress/gutenberg#81462: insert server-rendered HTML into the page and have its directives hydrated, without touching the rest of the island.
All demos use core blocks and run against the PR's CI build of Gutenberg.
The blueprint installs Gutenberg built from PR #81462 (the same build as ?gutenberg-pr=81462), installs the demo plugin from this repository, and seeds the content. The demo pages are linked in the site's navigation.
| Page | Demo | What it shows |
|---|---|---|
/rhd-compare/ |
data-wp-html vs renderHTML() |
The same trusted, server-rendered fragment inserted two ways. With data-wp-html (merged in #83092) it is inert; with renderHTML() its context, events and bindings work, and earlier inserts keep their state. |
/rhd-load-more/ |
Query Loop "Load more" (#31446) | Page N rendered by the Query block's own Post Template on the server and appended. Existing posts keep their state and appended posts are interactive. About 11 KB per page instead of a 78 KB full page. |
/rhd-personalize/ |
Personalized region on a cacheable page (#80521) | The page HTML is identical for every visitor. Only the visitor-dependent region is re-rendered on the server and patched in: 2.4 KB instead of a 74 KB full-page refetch. Keyed items and unrelated islands keep their state. |
/rhd-comments/ |
Comments without a page reload (#53737) | A new comment rendered by the core Comment Template block and inserted hydrated, plus the updated "N responses" heading from the same response. |
Two variants show limitations of the PR as it stands:
/rhd-load-more/?rhd-state=private: the core Image lightbox in appended posts needs the server state its block registered.renderHTML()has no way to merge it, andcore/imagelocks its store. This variant merges it through the router's privatepopulateServerData()to show the lightbox working./rhd-load-more-default/: the same "Load more" on a Query block with "Force page reload" on, the default. The list isn't inside an island, sorenderHTML()appends nothing.
render-html-demos/: the WordPress plugin. PHP-only dynamic blocks, REST endpoints that return fragments, and script modules. No build step.blueprints/playground.json: the Playground blueprint behind the link above.blueprints/local.json: the blueprint for local runs with mounted directories.validate/: a Playwright script that drives every demo, asserts its behaviour, measures payloads and records a video per demo.validate/results/: screenshots, videos andresults.jsonfrom the last validation run.
# Gutenberg built from the PR (the artifact Playground uses)
curl -L -o gutenberg.zip "https://playground.wordpress.net/plugin-proxy.php?org=WordPress&repo=gutenberg&workflow=Build%20Gutenberg%20Plugin%20Zip&artifact=gutenberg.zip&pr=81462"
unzip gutenberg.zip -d gutenberg
npx @wp-playground/cli@latest server --port=9400 \
--blueprint=blueprints/local.json \
--mount=./gutenberg:/wordpress/wp-content/plugins/gutenberg \
--mount=./render-html-demos:/wordpress/wp-content/plugins/render-html-demos \
--define-bool SCRIPT_DEBUG trueThen open http://127.0.0.1:9400/rhd-compare/.
cd validate
npm install
npx playwright install chromium
BASE=http://127.0.0.1:9400 npm run validateEach check reports PASS, FAIL, or GAP. GAP marks a check that documents a known limitation of the PR as it stands: it's expected to fail until the PR addresses it.
Last run (WordPress 7.1.3, PR head 2c9f257f): 38 passed, 5 known gaps confirmed, 0 unexpected failures. Timings come from PHP-WASM and aren't representative, so only payload sizes are reported.
These are confirmed by the GAP checks:
renderHTML()throws when given anasDangerousHTML()value, the trust wrapperdata-wp-htmlrequires. A nativeTrustedHTMLvalue works.- A fragment can't bring the Interactivity API state its blocks registered on the server, so the core Image lightbox doesn't work in appended posts.
- When the container isn't inside an island, only islands at the top level of the inserted HTML are found. On a default Query block nothing is appended, and with
SCRIPT_DEBUGoff there is no warning.
GPL-2.0-or-later