H
Hono2mo ago
schettn

How to implement renderToPipeableStream with the streaming API?

return stream(c, async (stream) => {
const {pipe} = reactServer.renderToPipeableStream(
<></>
, {
onShellReady: async () => {
c.header('Content-Type', 'text/html')

// What to do here?
// i want to stream the react data
},
onShellError: async (error) => {
// What to do here?
// I want to return a 500 error with a dummy html page
}
})
})
return stream(c, async (stream) => {
const {pipe} = reactServer.renderToPipeableStream(
<></>
, {
onShellReady: async () => {
c.header('Content-Type', 'text/html')

// What to do here?
// i want to stream the react data
},
onShellError: async (error) => {
// What to do here?
// I want to return a 500 error with a dummy html page
}
})
})
Is this even a correct use-case for the hono streaming api?
7 Replies
ambergristle
ambergristle2mo ago
You can pipe a readable stream to the hono stream that gets returned to the client Idk if pipe in your snippet is a readable stream. I haven’t used that lib. If it’s not, maybe the lib has a readable stream method? As far as error responses, it doesn’t look like you can return a 500. Once the stream is opened, you’re locked in https://hono.dev/docs/helpers/streaming
schettn
schettnOP2mo ago
React server has a renderToReadableStream but it is not supported in node enviroments. When does the stream open? When you first put data inside or earlier? onShellReady and onShellError are exclusive.
ambergristle
ambergristle2mo ago
By the time the callback is called, I think. Check the docs I linked
schettn
schettnOP2mo ago
"However, when the callback function is executed, the stream has already started, so it cannot be overwritten." Okay thanks, so i cannot use the streaming api.
ambergristle
ambergristle2mo ago
I guess not What’s your goal/motivation?
schettn
schettnOP2mo ago
I want to SSR stream react with hono (nodejs) https://react.dev/reference/react-dom/server/renderToPipeableStream I got it working using a promise based approach:
return await new Promise<Response>((resolve, reject) => {
const {pipe} = reactServer.renderToPipeableStream(
<App />,
{
bootstrapModules: ['/__pylon/static/app.js'],
bootstrapScriptContent: `window.__PYLON_DATA__ = ${JSON.stringify(
{
pageProps: pageProps,
cacheSnapshot: cacheSnapshot
}
)}`,
onShellReady: async () => {
c.header('Content-Type', 'text/html')

const passThrough = new PassThrough()

pipe(passThrough)

resolve(c.body(Readable.toWeb(passThrough) as any))
},
onShellError: async error => {
reject(error)
}
}
)
})
return await new Promise<Response>((resolve, reject) => {
const {pipe} = reactServer.renderToPipeableStream(
<App />,
{
bootstrapModules: ['/__pylon/static/app.js'],
bootstrapScriptContent: `window.__PYLON_DATA__ = ${JSON.stringify(
{
pageProps: pageProps,
cacheSnapshot: cacheSnapshot
}
)}`,
onShellReady: async () => {
c.header('Content-Type', 'text/html')

const passThrough = new PassThrough()

pipe(passThrough)

resolve(c.body(Readable.toWeb(passThrough) as any))
},
onShellError: async error => {
reject(error)
}
}
)
})
renderToPipeableStream – React
The library for web and native user interfaces
ambergristle
ambergristle2mo ago
dope! thanks for sharing your solution

Did you find this page helpful?