MENU
.renderToNodeStream()
Switching to streams means that the webpage is displayed simultaneously as it is being loaded. This improves the performance, which is especially important when the download size is big.
('ReactDOMServer.renderToNodeStream()' was deprecated in React 18 and removed in React 19 — even before removal, it buffered its entire output rather than truly streaming, so it offered little benefit. The current replacement is 'ReactDOMServer.renderToPipeableStream()', shown below, which supports real streaming and Suspense.)
// MyProject/server.jsimport express from "express";import React from "react";import ReactDOMServer from "react-dom/server";import App from "./public/components/App.js";var app = express();app.use(express.static("./dist/public"));app.get('/', (req,res)=>{
const htmlStart = `
<!DOCTYPE html><html>
<head></head>
<body>
<div id="root">`;
const htmlEnd = `</div>
<script src="/home.js" type="module"></script>
</body>
</html>`;
const { pipe } = ReactDOMServer.renderToPipeableStream(<App msg="hi" />, {
onShellReady() {
res.write(htmlStart);
pipe(res, { end: false });
},
onAllReady() {
res.write(htmlEnd);
res.end();
},
onError(err) {
console.error(err);
}
});}); app.listen(4000);console.log('Running an Express server at http://localhost:4000/');Likewise, 'ReactDOMServer.renderToStaticNodeStream()' — the non-hydrating counterpart of 'renderToNodeStream()' — is also removed as of React 19. For static markup with no hydration, pipe from the onAllReady callback instead of onShellReady when using 'renderToPipeableStream()' above, or use the newer 'prerenderToNodeStream()' API added in React 19, which is purpose-built for static site generation.