Skip to content

Commit

Permalink
Fix rsc bootstrap buffer missing in the future renders (#34631)
Browse files Browse the repository at this point in the history
## Bug

If there's upcoming streaming data from server components, should safely skip the bootstrap process. Previously we deleted the buffer then it will cause the buffer is missing in the later re-renders. Now we mark it as empty array, so it can safely skip the boostrap phase

x-ref: #34475

- [x] Related issues linked using `fixes #number`
- [x] Integration tests added
- [x] Errors have helpful link attached, see `contributing.md`
  • Loading branch information
huozhi committed Feb 21, 2022
1 parent 0243e6e commit f110a37
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 1 deletion.
4 changes: 3 additions & 1 deletion packages/next/client/index.tsx
Expand Up @@ -702,7 +702,9 @@ if (process.env.__NEXT_RSC) {
writer.write(encoder.encode(val))
})
buffer.length = 0
serverDataBuffer.delete(key)
// Clean buffer but not deleting the key to mark bootstrap as complete.
// Then `nextServerDataCallback` will be safely skipped in the future renders.
serverDataBuffer.set(key, [])
}
serverDataWriter.set(key, writer)
}
Expand Down
@@ -1,6 +1,7 @@
const withReact18 = require('../../react-18/test/with-react-18')

module.exports = withReact18({
trailingSlash: true,
reactStrictMode: true,
onDemandEntries: {
maxInactiveAge: 1000 * 60 * 60,
Expand Down
@@ -0,0 +1,23 @@
import { Suspense } from 'react'

let result
let promise
function Data() {
if (result) return result
if (!promise)
promise = new Promise((res) => {
setTimeout(() => {
result = 'next_streaming_data'
res()
}, 500)
})
throw promise
}

export default function Page() {
return (
<Suspense fallback="next_streaming_fallback">
<Data />
</Suspense>
)
}
Expand Up @@ -82,6 +82,12 @@ export default function (context, { runtime, env }) {
expect(await browser.eval('window.beforeNav')).toBe(1)
})

it('should handle streaming server components correctly', async () => {
const browser = await webdriver(context.appPort, '/streaming-rsc')
const content = await browser.eval(`window.document.body.innerText`)
expect(content).toMatchInlineSnapshot('"next_streaming_data"')
})

// Disable next/image for nodejs runtime temporarily
if (runtime === 'edge') {
it('should suspense next/image in server components', async () => {
Expand Down

0 comments on commit f110a37

Please sign in to comment.