Skip to content

Instantly share code, notes, and snippets.

@mhart
Last active June 26, 2024 02:42
Show Gist options
  • Save mhart/f29345a8f192cbc3f8ea91bcb89e4053 to your computer and use it in GitHub Desktop.
Save mhart/f29345a8f192cbc3f8ea91bcb89e4053 to your computer and use it in GitHub Desktop.
PPR w/ CF Pages and HTMLRewriter
// functions/index.js
export async function onRequestGet({ request, env }) {
// Start getting something from "the DB"
const dbPromise = scheduler.wait(1000).then(() => new Date().toDateString());
// Fetch index.html from cache (body will stream below)
const staticShell = await env.ASSETS.fetch(request);
// The browser will immediately render up until the body closing tag,
// then we insert dom modification scripts as the data is resolved
return new HTMLRewriter()
.on('body', {
element(e) {
e.onEndTag(async (tag) => {
const data = await dbPromise;
tag
.before('<template id="date-tpl">', { html: true })
.before(data)
.before('</template>', { html: true })
.before(
`<script>
document.getElementById("date").replaceChildren(
document.getElementById("date-tpl").content)
</script>`,
{ html: true }
);
});
},
})
.transform(
new Response(staticShell.body, {
headers: { 'content-type': 'text/html; charset=utf-8' },
})
);
}
<!-- static/index.html -->
<html>
<body>
<p>Today is: <span id="date">Loading...</span></p>
</body>
</html>
#:schema node_modules/wrangler/config-schema.json
name = "pages-ppr"
pages_build_output_dir = "./static"
compatibility_date = "2024-05-12"
@mhart
Copy link
Author

mhart commented May 15, 2024

To deploy:

npx wrangler pages deploy

To develop locally (may have issues with streaming unless you turn gzip off – so use curl to verify):

npx wrangler pages dev

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment