Vike not only has first-class support for HTML streaming (aka SSR streaming), but also provides you with extensive control over the HTML stream.
If you merely want to enable/disable HTML streaming, see the stream setting instead.
Instead of manually integrating HTML Streaming yourself, you can use a UI framework Vike extensionvike-react/vike-vue/vike-solid which already integrates HTML Streaming. And you can use Bati to scaffold an app that uses vike-react/vike-vue/vike-solid.
⚠️
The documentation on this page is meant for users who want to manually integrate HTML Streaming. If you use vike-react/vike-vue/vike-solid then HTML Streaming is already built-in and you can 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 (and already hydrated).
Instead of using HTML streaming, an easy alternative is to use a stateful component. But the issue with that approach is that the content isn't rendered to HTML. For example, a product page fetching its content from a database won't get the SEO and performance advantages of SSR.
With HTML streaming, all content is rendered to HTML.
Vike has first-class support for HTML streaming and progressive rendering.