rwsdk
Version:
Build fast, server-driven webapps on Cloudflare with SSR, RSC, and realtime
40 lines (39 loc) • 2.08 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { Preloads } from "./preloads.js";
import { Stylesheets } from "./stylesheets.js";
import { createThenableFromReadableStream, renderHtmlStream, } from "rwsdk/__ssr_bridge";
import { stitchDocumentAndAppStreams } from "../lib/stitchDocumentAndAppStreams.js";
export const renderDocumentHtmlStream = async ({ rscPayloadStream, Document, requestInfo, shouldSSR, onError, }) => {
// Extract the app node from the RSC payload
const rscAppThenable = createThenableFromReadableStream(rscPayloadStream);
const { node: innerAppNode } = (await rscAppThenable);
// todo(justinvdm, 18 Jun 2025): We can build on this later to allow users
// surface context. e.g:
// * we assign `user: requestInfo.clientCtx` here
// * user populates requestInfo.clientCtx on worker side
// * user can import a read only `import { clientCtx } from "rwsdk/client"`
// on client side
const clientContext = {
rw: {
ssr: shouldSSR,
},
};
// Create the outer document with a marker for injection
const documentElement = (_jsxs(Document, { ...requestInfo, children: [_jsx("script", { nonce: requestInfo.rw.nonce, dangerouslySetInnerHTML: {
__html: `globalThis.__RWSDK_CONTEXT = ${JSON.stringify(clientContext)}`,
} }), _jsx(Stylesheets, { requestInfo: requestInfo }), _jsx(Preloads, { requestInfo: requestInfo }), _jsx("div", { id: "hydrate-root", children: _jsx("div", { id: "rwsdk-app-start" }) })] }));
const outerHtmlStream = await renderHtmlStream({
node: documentElement,
requestInfo,
onError,
identifierPrefix: "__RWSDK_DOCUMENT__",
});
const appHtmlStream = await renderHtmlStream({
node: innerAppNode,
requestInfo,
onError,
});
// Stitch the streams together
const stitchedStream = stitchDocumentAndAppStreams(outerHtmlStream, appHtmlStream, '<div id="rwsdk-app-start"></div>', '<div id="rwsdk-app-end"></div>');
return stitchedStream;
};