Fix rsc bootstrap buffer missing in the future renders (#34631)
## 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`
This commit is contained in:
parent
0243e6e95d
commit
f110a3735b
4 changed files with 33 additions and 1 deletions
|
@ -702,7 +702,9 @@ if (process.env.__NEXT_RSC) {
|
||||||
writer.write(encoder.encode(val))
|
writer.write(encoder.encode(val))
|
||||||
})
|
})
|
||||||
buffer.length = 0
|
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)
|
serverDataWriter.set(key, writer)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
const withReact18 = require('../../react-18/test/with-react-18')
|
const withReact18 = require('../../react-18/test/with-react-18')
|
||||||
|
|
||||||
module.exports = withReact18({
|
module.exports = withReact18({
|
||||||
|
trailingSlash: true,
|
||||||
reactStrictMode: true,
|
reactStrictMode: true,
|
||||||
onDemandEntries: {
|
onDemandEntries: {
|
||||||
maxInactiveAge: 1000 * 60 * 60,
|
maxInactiveAge: 1000 * 60 * 60,
|
||||||
|
|
|
@ -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>
|
||||||
|
)
|
||||||
|
}
|
|
@ -82,6 +82,12 @@ export default function (context, { runtime, env }) {
|
||||||
expect(await browser.eval('window.beforeNav')).toBe(1)
|
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
|
// Disable next/image for nodejs runtime temporarily
|
||||||
if (runtime === 'edge') {
|
if (runtime === 'edge') {
|
||||||
it('should suspense next/image in server components', async () => {
|
it('should suspense next/image in server components', async () => {
|
||||||
|
|
Loading…
Reference in a new issue