mirror of
https://github.com/oven-sh/bun
synced 2026-02-13 04:18:58 +00:00
58 lines
1.9 KiB
TypeScript
58 lines
1.9 KiB
TypeScript
import type { ReactNode } from "react";
|
|
import { createFromReadableStream } from "react-server-dom-bun/client.browser";
|
|
import { store, type Store } from "./simple-store.ts";
|
|
|
|
export type NonNullishReactNode = Exclude<ReactNode, null | undefined>;
|
|
export type RenderableRscPayload = Promise<NonNullishReactNode> | NonNullishReactNode;
|
|
|
|
const encoder = new TextEncoder();
|
|
|
|
function enqueueChunks(
|
|
controller: ReadableStreamDefaultController<Uint8Array<ArrayBuffer>>,
|
|
...chunks: (string | Uint8Array<ArrayBuffer>)[]
|
|
) {
|
|
for (let chunk of chunks) {
|
|
if (typeof chunk === "string") {
|
|
chunk = encoder.encode(chunk);
|
|
}
|
|
|
|
controller.enqueue(chunk);
|
|
}
|
|
}
|
|
|
|
// The initial RSC payload is put into inline <script> tags that follow the pattern
|
|
// `(self.__bun_f ??= []).push(chunk)`, which is converted into a ReadableStream
|
|
// here for React hydration. Since inline scripts are executed immediately, and
|
|
// this file is loaded asynchronously, the `__bun_f` becomes a clever way to
|
|
// stream the arbitrary data while HTML is loading. In a static build, this is
|
|
// setup as an array with one string.
|
|
const initialRscStream = createFromReadableStream(
|
|
new ReadableStream<NonNullishReactNode>({
|
|
start(controller) {
|
|
const bunF = (self.__bun_f ??= []);
|
|
const originalPush = bunF.push;
|
|
|
|
bunF.push = function (this: typeof bunF, ...chunks: (string | Uint8Array<ArrayBuffer>)[]) {
|
|
enqueueChunks(controller, ...chunks);
|
|
return originalPush.apply(this, chunks);
|
|
}.bind(bunF);
|
|
|
|
bunF.forEach(chunk => enqueueChunks(controller, chunk));
|
|
|
|
if (document.readyState === "loading") {
|
|
document.addEventListener(
|
|
"DOMContentLoaded",
|
|
() => {
|
|
controller.close();
|
|
},
|
|
{ once: true },
|
|
);
|
|
} else {
|
|
controller.close();
|
|
}
|
|
},
|
|
}),
|
|
);
|
|
|
|
export const APP_RSC_PAYLOAD: Store<RenderableRscPayload> = store(initialRscStream);
|