Skip to content

Commit 55c063e

Browse files
authored
Delay prefix flushing (#35170)
Only happened with SSR without suspense case Similar reason to #34474, the prefix (script parts) might be flushed during the render stream causing bad HTML. Use the same tricky to delay the prefix flushing #### Expected ```html <div>content</div> <!-- render stream --> <script>...</script> <!-- prefix --> ``` #### Observed ```html <!-- prefix choked the render stream --> <div <script>...</script> >content</div> ``` Test sample: https://next-react-server-components-r5xocii9r-huozhi.vercel.app/ssr
1 parent 201f98e commit 55c063e

File tree

1 file changed

+13
-4
lines changed

1 file changed

+13
-4
lines changed

packages/next/server/render.tsx

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1820,17 +1820,25 @@ function createPrefixStream(
18201820
prefix: string
18211821
): TransformStream<Uint8Array, Uint8Array> {
18221822
let prefixFlushed = false
1823+
let prefixPrefixFlushFinished: Promise<void> | null = null
18231824
return createTransformStream({
18241825
transform(chunk, controller) {
1826+
controller.enqueue(chunk)
18251827
if (!prefixFlushed && prefix) {
18261828
prefixFlushed = true
1827-
controller.enqueue(chunk)
1828-
controller.enqueue(encodeText(prefix))
1829-
} else {
1830-
controller.enqueue(chunk)
1829+
prefixPrefixFlushFinished = new Promise((res) => {
1830+
// NOTE: streaming flush
1831+
// Enqueue prefix part before the major chunks are enqueued so that
1832+
// prefix won't be flushed too early to interrupt the data stream
1833+
setTimeout(() => {
1834+
controller.enqueue(encodeText(prefix))
1835+
res()
1836+
})
1837+
})
18311838
}
18321839
},
18331840
flush(controller) {
1841+
if (prefixPrefixFlushFinished) return prefixPrefixFlushFinished
18341842
if (!prefixFlushed && prefix) {
18351843
prefixFlushed = true
18361844
controller.enqueue(encodeText(prefix))
@@ -1850,6 +1858,7 @@ function createInlineDataStream(
18501858
if (!dataStreamFinished) {
18511859
const dataStreamReader = dataStream.getReader()
18521860

1861+
// NOTE: streaming flush
18531862
// We are buffering here for the inlined data stream because the
18541863
// "shell" stream might be chunkenized again by the underlying stream
18551864
// implementation, e.g. with a specific high-water mark. To ensure it's

0 commit comments

Comments
 (0)