@redwoodjs/sdk
Version:
Build fast, server-driven webapps on Cloudflare with SSR, RSC, and realtime
57 lines (56 loc) • 2.52 kB
JavaScript
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
import { clientWebpackRequire } from "./imports/client";
// NOTE: `react-server-dom-webpack` uses this global to load modules,
// so we need to define it here before importing "react-server-dom-webpack."
globalThis.__webpack_require__ = clientWebpackRequire;
export const fetchTransport = (transportContext) => {
const fetchCallServer = async (id, args) => {
const { createFromFetch, encodeReply } = await import("react-server-dom-webpack/client.browser");
const url = new URL(window.location.href);
url.searchParams.set("__rsc", "");
if (id != null) {
url.searchParams.set("__rsc_action_id", id);
}
const streamData = createFromFetch(fetch(url, {
method: "POST",
body: args != null ? await encodeReply(args) : null,
}), { callServer: fetchCallServer });
transportContext.setRscPayload(streamData);
const result = await streamData;
return result.actionResult;
};
return fetchCallServer;
};
export const initClient = async ({ transport = fetchTransport, } = {}) => {
const transportContext = {
setRscPayload: () => { },
};
const callServer = transport(transportContext);
globalThis.__rsc_callServer = callServer;
const rootEl = document.getElementById("root");
if (!rootEl) {
throw new Error('no element with id "root"');
}
const React = await import("react");
const { hydrateRoot } = await import("react-dom/client");
// @ts-ignore: todo(peterp, 2024-11-27): Type these properly.
const { createFromReadableStream, createFromFetch, encodeReply } = await import("react-server-dom-webpack/client.browser");
const { rscStream } = await import("rsc-html-stream/client");
let rscPayload;
rscPayload ??= createFromReadableStream(rscStream, {
callServer,
});
function Content() {
const [streamData, setStreamData] = React.useState(rscPayload);
const [_isPending, startTransition] = React.useTransition();
transportContext.setRscPayload = (v) => startTransition(() => setStreamData(v));
return _jsx(_Fragment, { children: React.use(streamData).node });
}
hydrateRoot(rootEl, _jsx(Content, {}));
if (import.meta.hot) {
import.meta.hot.on("rsc:update", (e) => {
console.log("[rw-sdk] hot update", e.file);
callServer("__rsc_hot_update", [e.file]);
});
}
};