import {use, Suspense, useState, startTransition, Profiler} from 'react';
import ReactDOM from 'react-dom/client';
import {createFromFetch, encodeReply} from 'react-server-dom-webpack/client';
import './style.css';
function findSourceMapURL(fileName) {
return (
document.location.origin +
'/source-maps?name=' +
encodeURIComponent(fileName)
);
}
async function createWebSocketStream(url) {
const ws = new WebSocket(url);
ws.binaryType = 'arraybuffer';
await new Promise((resolve, reject) => {
ws.addEventListener('open', resolve, {once: true});
ws.addEventListener('error', reject, {once: true});
});
const writable = new WritableStream({
write(chunk) {
ws.send(chunk);
},
close() {
ws.close();
},
abort(reason) {
ws.close(1000, reason && String(reason));
},
});
const readable = new ReadableStream({
start(controller) {
ws.addEventListener('message', event => {
controller.enqueue(event.data);
});
ws.addEventListener('close', () => {
controller.close();
});
ws.addEventListener('error', err => {
controller.error(err);
});
},
});
return {readable, writable};
}
let updateRoot;
async function callServer(id, args) {
let response;
if (process.env.NODE_ENV === 'development') {
const requestId = crypto.randomUUID();
const debugChannel = await createWebSocketStream(
`ws://localhost:3001/debug-channel?id=${requestId}`
);
response = createFromFetch(
fetch('/', {
method: 'POST',
headers: {
Accept: 'text/x-component',
'rsc-action': id,
'rsc-request-id': requestId,
},
body: await encodeReply(args),
}),
{
callServer,
debugChannel,
findSourceMapURL,
}
);
} else {
response = createFromFetch(
fetch('/', {
method: 'POST',
headers: {
Accept: 'text/x-component',
'rsc-action': id,
},
body: await encodeReply(args),
}),
{
callServer,
findSourceMapURL,
}
);
}
const {returnValue, root} = await response;
startTransition(() => {
updateRoot(root);
});
return returnValue;
}
function Shell({data}) {
const [root, setRoot] = useState(data);
updateRoot = setRoot;
return root;
}
async function hydrateApp() {
let response;
if (process.env.NODE_ENV === 'development') {
const requestId = crypto.randomUUID();
const debugChannel = await createWebSocketStream(
`ws://localhost:3001/debug-channel?id=${requestId}`
);
response = createFromFetch(
fetch('/', {
headers: {
Accept: 'text/x-component',
'rsc-request-id': requestId,
},
}),
{
callServer,
debugChannel,
findSourceMapURL,
}
);
} else {
response = createFromFetch(
fetch('/', {
headers: {
Accept: 'text/x-component',
},
}),
{
callServer,
findSourceMapURL,
}
);
}
const {root, returnValue, formState} = await response;
ReactDOM.hydrateRoot(
document,
<Profiler id="root">
<Shell data={root} />
</Profiler>,
{
formState: formState,
}
);
}
hydrateApp();