Skip to content

Commit

Permalink
Make router able to navigate between rsc pages
Browse files Browse the repository at this point in the history
  • Loading branch information
huozhi committed Mar 15, 2022
1 parent ed1eeda commit 540ec0d
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 29 deletions.
37 changes: 15 additions & 22 deletions packages/next/client/index.tsx
Expand Up @@ -707,10 +707,6 @@ if (process.env.__NEXT_RSC) {
buffer.forEach((val) => {
writer.write(encoder.encode(val))
})
buffer.length = 0
// 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 Expand Up @@ -754,21 +750,24 @@ if (process.env.__NEXT_RSC) {
if (response) return response

const bufferCacheKey = cacheKey + ',' + router.route + ',' + id
if (serverDataBuffer.has(bufferCacheKey)) {
const hasKey = serverDataBuffer.has(bufferCacheKey)
if (hasKey) {
const t = new TransformStream()
const writer = t.writable.getWriter()
response = createFromFetch(Promise.resolve({ body: t.readable }))
nextServerDataRegisterWriter(bufferCacheKey, writer)
} else {
response = createFromFetch(
serialized
? (() => {
const t = new TransformStream()
t.writable.getWriter().write(new TextEncoder().encode(serialized))
return Promise.resolve({ body: t.readable })
})()
: fetchFlight(getCacheKey())
)
const fetchPromise = serialized
? (() => {
const t = new TransformStream()
const writer = t.writable.getWriter()
writer.ready.then(() => {
writer.write(new TextEncoder().encode(serialized))
})
return Promise.resolve({ body: t.readable })
})()
: fetchFlight(getCacheKey())
response = createFromFetch(fetchPromise)
}

rscCache.set(cacheKey, response)
Expand All @@ -778,11 +777,9 @@ if (process.env.__NEXT_RSC) {
const ServerRoot = ({
cacheKey,
serialized,
_fresh,
}: {
cacheKey: string
serialized?: string
_fresh?: boolean
}) => {
React.useEffect(() => {
rscCache.delete(cacheKey)
Expand All @@ -794,7 +791,7 @@ if (process.env.__NEXT_RSC) {

RSCComponent = (props: any) => {
const cacheKey = getCacheKey()
const { __flight_serialized__, __flight_fresh__ } = props
const { __flight_serialized__ } = props
const [, dispatch] = useState({})
const startTransition = (React as any).startTransition
const renrender = () => dispatch({})
Expand All @@ -813,11 +810,7 @@ if (process.env.__NEXT_RSC) {

return (
<RefreshContext.Provider value={refreshCache}>
<ServerRoot
cacheKey={cacheKey}
serialized={__flight_serialized__}
_fresh={__flight_fresh__}
/>
<ServerRoot cacheKey={cacheKey} serialized={__flight_serialized__} />
</RefreshContext.Provider>
)
}
Expand Down
Expand Up @@ -14,6 +14,11 @@ export default function Index({ header, router }) {
<div>
<Foo />
</div>
<div>
<Link href={'/next-api/link'}>
<a id="next-link">next link</a>
</Link>
</div>
<Link href={'/'}>
<a id="refresh">refresh</a>
</Link>
Expand Down
Expand Up @@ -6,12 +6,16 @@ export default function LinkPage({ router }) {
return (
<>
<h3 id="query">query:{id}</h3>
<Link href={`/next-api/link?id=${id + 1}`}>
<a id="next_id">next id</a>
</Link>
<Link href={`/`}>
<a>go home</a>
</Link>
<div>
<Link href={`/next-api/link?id=${id + 1}`}>
<a id="next_id">next id</a>
</Link>
</div>
<div>
<Link href={`/`}>
<a id="home">go home</a>
</Link>
</div>
</>
)
}
Expand Up @@ -70,7 +70,10 @@ export default function (context, { runtime, env }) {

it('should support next/link in server components', async () => {
const linkHTML = await renderViaHTTP(context.appPort, '/next-api/link')
const linkText = getNodeBySelector(linkHTML, '#__next > a[href="/"]').text()
const linkText = getNodeBySelector(
linkHTML,
'#__next > div > a[href="/"]'
).text()

expect(linkText).toContain('go home')

Expand All @@ -92,6 +95,22 @@ export default function (context, { runtime, env }) {
expect(await browser.eval('window.beforeNav')).toBe(1)
})

it('should be able to navigate between rsc pages', async () => {
const browser = await webdriver(context.appPort, '/')

await browser.waitForElementByCss('#next-link').click()
await new Promise((res) => setTimeout(res, 1000))
expect(await browser.url()).toBe(
`http://localhost:${context.appPort}/next-api/link`
)
await browser.waitForElementByCss('#home').click()
await new Promise((res) => setTimeout(res, 1000))
expect(await browser.url()).toBe(`http://localhost:${context.appPort}/`)
const homeContent = await browser.elementByCss('#__next').text()
console.log('homeContent', homeContent)
expect(homeContent).toContain('component:index.server')
})

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`)
Expand Down

0 comments on commit 540ec0d

Please sign in to comment.