Skip to main content

renderToPipeableStream

renderToPipeableStream renders a React tree to a Node.js Writable stream. This is the recommended API for server-side rendering in Node.js environments with full support for Suspense, streaming, and selective hydration.
This is the modern replacement for renderToString in Node.js. It supports streaming, Suspense, and provides better performance and user experience.

Reference

renderToPipeableStream(element, options?)

Renders a React element to a pipeable stream with progressive HTML streaming.

Parameters

  • element: ReactNode - The React element to render
  • options: Object (optional)
    • identifierPrefix: string - Prefix for IDs generated by useId
    • namespaceURI: string - Namespace URI for the document (e.g., SVG)
    • nonce: string | { script?: string, style?: string } - Nonce for Content Security Policy
    • bootstrapScriptContent: string - Inline script content to run before other scripts
    • bootstrapScripts: Array<string | BootstrapScriptDescriptor> - External scripts to load
    • bootstrapModules: Array<string | BootstrapScriptDescriptor> - External ES modules to load
    • progressiveChunkSize: number - Target size of progressive chunks
    • onShellReady: () => void - Called when the shell (initial UI) is ready
    • onShellError: (error: mixed) => void - Called if the shell fails to render
    • onAllReady: () => void - Called when all content, including Suspense boundaries, is ready
    • onError: (error: mixed, errorInfo: ErrorInfo) => ?string - Error handler for rendering errors
    • unstable_externalRuntimeSrc: string | BootstrapScriptDescriptor - External React runtime script
    • importMap: ImportMap - Import map for module scripts
    • formState: ReactFormState | null - Form state for progressive enhancement
    • onHeaders: (headers: HeadersDescriptor) => void - Callback for early hints
    • maxHeadersLength: number - Maximum length for early hints headers

Returns

Returns an object with two methods:
  • pipe(destination): Pipes the HTML stream to a Node.js Writable stream (like http.ServerResponse)
  • abort(reason): Aborts the render and puts remaining content into client-rendered mode

Caveats

  • Node.js only: This API uses Node.js stream APIs (Writable)
  • One-time pipe: Can only pipe to one destination stream
  • Call in onShellReady: Typically pipe in the onShellReady callback
  • Edge runtimes: For edge environments, use renderToReadableStream

Usage

Basic streaming in Express

Streaming with Suspense

onShellReady vs onAllReady

Choose when to start streaming based on your use case:

Error handling

Complete HTML document

Render a complete HTML document with proper structure:

Using bootstrap scripts and modules

Setting CSP nonce

Advanced Patterns

Implementing timeouts

Custom HTML streaming wrapper

Implementing early hints (HTTP 103)

Resuming from postponed state

Comparison with Other APIs

Pros:
  • Streaming support
  • Suspense support
  • Progressive rendering
  • Better performance
  • Non-blocking

Common Issues

pipe() can only be called once per render:
Solution: Create a new render for each response.
Don’t call pipe() before setting response headers:
If a component outside Suspense boundaries throws a promise, rendering hangs:
Each render keeps state in memory until complete:

Performance Best Practices

Stream immediately to minimize time to first byte:
Control streaming granularity:
Prevent hanging renders:
Place boundaries around slow content:

See Also