๐Ÿ“ฆ noxify / vite-rsc-ssg-renoun

๐Ÿ“„ entry.ssr.tsx ยท 48 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48import { createFromReadableStream } from '@vitejs/plugin-rsc/ssr'
import React from 'react'
import { renderToReadableStream } from 'react-dom/server.edge'
import { prerender } from 'react-dom/static.edge'
import { injectRSCPayload } from 'rsc-html-stream/server'
import type { RscPayload } from './shared'

/**
 * Server-side rendering (SSR) entrypoint for Vite RSC/SSR pipeline.
 * Handles rendering of HTML streams from RSC payloads for both SSG and SSR.
 *
 * @param rscStream - The readable stream containing the RSC payload
 * @param options - Optional options (e.g. ssg: true for static generation)
 * @returns A readable stream of HTML (with injected RSC payload)
 */
export async function renderHtml(
  rscStream: ReadableStream<Uint8Array>,
  options?: {
    ssg?: boolean
  },
): Promise<ReadableStream<Uint8Array>> {
  const [rscStream1, rscStream2] = rscStream.tee()

  let payload: Promise<RscPayload>
  function SsrRoot() {
    payload ??= createFromReadableStream<RscPayload>(rscStream1)
    const root = React.use(payload).root
    return root
  }
  const bootstrapScriptContent =
    await import.meta.viteRsc.loadBootstrapScriptContent('index')

  let htmlStream: ReadableStream<Uint8Array>
  if (options?.ssg) {
    const prerenderResult = await prerender(<SsrRoot />, {
      bootstrapScriptContent,
    })
    htmlStream = prerenderResult.prelude
  } else {
    htmlStream = await renderToReadableStream(<SsrRoot />, {
      bootstrapScriptContent,
    })
  }

  let responseStream: ReadableStream<Uint8Array> = htmlStream
  responseStream = responseStream.pipeThrough(injectRSCPayload(rscStream2))
  return responseStream
}