Instead of manually integrating HTML streaming yourself, you can use a UI framework Vike extension (vike-react/vike-vue/vike-solid) which already integrates HTML streaming. You can use Bati to scaffold an app that uses vike-react/vike-vue/vike-solid.
The documentation on this page is meant for expert users who want to manually integrate HTML Streaming. If you use vike-react/vike-vue/vike-solid then HTML Streaming is already completely integrated which means you can usually skip reading this page.
Examples
Examples of manually integrating HTML Streaming (without using a Vike extension).
In general, we recommend using pageContext.httpResponse.pipe() because pipe() is able to flush streams. In other words: the stream provided by your UI framework can say "now is a good time to flush the buffer and send it to the user".
As far as we know, only React leverages the flush capability. Thus, the recommendation may be irrelevant if you use a UI framework other than React.
If your server doesn't expose a writable stream then you cannot use pipe(). In that case you can fallback to:
pageContext.httpResponse.getReadableWebStream()
pageContext.httpResponse.getReadableNodeStream()
For example, Cloudflare Workers doesn't expose any writable stream and the only option is to use getReadableWebStream().
pageContext promise: You can return a pageContext promise, in order to send initial data to the client after the stream ends.
enableEagerStreaming
By default, the HTML stream isn't immediately sent to the user.
Instead, Vike awaits for your UI framework to start its stream.
If you set pageContext.enableEagerStreaming to true then Vike starts emitting the HTML template right away.
Make sure your server (or any proxy between your server and the user) doesn't buffer the stream, otherwise you may still notice a delay.
stampPipe()
If your UI framework provides a stream pipe, then you need to use stampPipe().
For Node.js:
If your server expects a readable stream (e.g. Cloudflare Workers) you can use new TransformStream():
For some UI frameworks, such as Vue, you need a pipe wrapper:
See /examples/cloudflare-workers-vue for an example of using a pipe wrapper with Vue's pipeToWebWritable()/pipeToNodeWritable(), as well as using new TransformStream() for Cloudflare Workers.
Consequently, you can determine the initial data (which needs to be passed to the client-side) only after the stream has ended.
In such situations, you can return a pageContext async function in your onRenderHtml() hook:
Progressive Rendering
Some UI frameworks, such as React, support progressive rendering: while some parts of the UI are being loaded, other parts are already rendered (as well as hydrated).
Demo:
Vike has first-class support for progressive rendering. (Make sure your UI framework supports progressive rendering.)