/
githubmr
/
facebook-react
Обзор
Документация
Войти
/
githubmr
/
facebook-react
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
main
fixtures/flight/src/index.js
161 строка
4 KB
Hendrik Liebau
[Flight] Use more robust web socket implementation in fixture (#34338)
29 авг 2025, 13:04
Не верифицирован
29 авг 2025, 13:04
3fe51c9
Код
Авторство
О чём код?
import * as React from 'react'; import {use, Suspense, useState, startTransition, Profiler} from 'react'; import ReactDOM from 'react-dom/client'; import {createFromFetch, encodeReply} from 'react-server-dom-webpack/client'; // TODO: This should be a dependency of the App but we haven't implemented CSS in Node yet. 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; // Refresh the tree with the new RSC payload. 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>, { // TODO: This part doesn't actually work because the server only returns // form state during the request that submitted the form. Which means it // the state needs to be transported as part of the HTML stream. We intend // to add a feature to Fizz for this, but for now it's up to the // metaframework to implement correctly. formState: formState, } ); } // Remove this line to simulate MPA behavior hydrateApp();