豆豆友情提示:这是一个非官方 GitHub 代理镜像,主要用于网络测试或访问加速。请勿在此进行登录、注册或处理任何敏感信息。进行这些操作请务必访问官方网站 github.com。 Raw 内容也通过此代理提供。
Skip to content

Commit fda89e4

Browse files
committed
Honor rewrites in fallback hydration
1 parent db7a645 commit fda89e4

File tree

3 files changed

+121
-6
lines changed

3 files changed

+121
-6
lines changed

packages/next/src/client/app-index.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -337,8 +337,9 @@ if (instantTestStaticFetch) {
337337

338338
return createInitialRSCPayloadFromFallbackPrerender(
339339
await processedResponse,
340-
fallbackInitialRSCPayload,
341-
renderedUrl
340+
// Let rewritten-path/query headers on the fetched fallback response win
341+
// over the current document URL when the host remaps the request.
342+
fallbackInitialRSCPayload
342343
)
343344
})()
344345
} else if (

packages/next/src/client/flight-data-helpers.test.ts

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,4 +405,110 @@ describe('createInitialRSCPayloadFromFallbackPrerender', () => {
405405
expect(payload.f[0][2]).toBe('head-node')
406406
expect(payload.f[0][3]).toBe(true)
407407
})
408+
409+
it('prefers rewritten headers over the rendered URL override', () => {
410+
const fallbackInitialRSCPayload: InitialRSCPayload = {
411+
b: 'build-id',
412+
c: ['', 'docs', '%%drp:slug:abc123%%'],
413+
q: '',
414+
i: false,
415+
f: [
416+
[
417+
[
418+
'',
419+
{
420+
children: [
421+
'docs',
422+
{
423+
children: [['slug', '%%drp:slug:abc123%%', 'd', null], {}],
424+
},
425+
],
426+
},
427+
],
428+
null,
429+
'head-node',
430+
false,
431+
],
432+
],
433+
m: new Set(),
434+
G: [(() => null) as any, undefined],
435+
S: false,
436+
h: null,
437+
}
438+
439+
const response = new Response(null, {
440+
headers: {
441+
'x-nextjs-rewritten-path': '/docs/rewritten',
442+
'x-nextjs-rewritten-query': 'from=fetch',
443+
},
444+
})
445+
446+
const payload = createInitialRSCPayloadFromFallbackPrerender(
447+
response,
448+
fallbackInitialRSCPayload,
449+
new URL('https://example.com/docs/original?from=document')
450+
)
451+
452+
const patchedTree = payload.f[0][0]
453+
expect(patchedTree[1].children[0]).toBe('docs')
454+
expect(patchedTree[1].children[1].children[0]).toEqual([
455+
'slug',
456+
'rewritten',
457+
'd',
458+
null,
459+
])
460+
expect(payload.q).toBe('?from=fetch')
461+
expect(payload.c.join('/')).toBe('/docs/original?from=document')
462+
})
463+
464+
it('falls back to the rendered URL override when no rewritten headers are present', () => {
465+
const fallbackInitialRSCPayload: InitialRSCPayload = {
466+
b: 'build-id',
467+
c: ['', 'docs', '%%drp:slug:abc123%%'],
468+
q: '',
469+
i: false,
470+
f: [
471+
[
472+
[
473+
'',
474+
{
475+
children: [
476+
'docs',
477+
{
478+
children: [['slug', '%%drp:slug:abc123%%', 'd', null], {}],
479+
},
480+
],
481+
},
482+
],
483+
null,
484+
'head-node',
485+
false,
486+
],
487+
],
488+
m: new Set(),
489+
G: [(() => null) as any, undefined],
490+
S: false,
491+
h: null,
492+
}
493+
494+
const response = new Response(null, {
495+
headers: {},
496+
})
497+
498+
const payload = createInitialRSCPayloadFromFallbackPrerender(
499+
response,
500+
fallbackInitialRSCPayload,
501+
new URL('https://example.com/docs/original?from=document')
502+
)
503+
504+
const patchedTree = payload.f[0][0]
505+
expect(patchedTree[1].children[0]).toBe('docs')
506+
expect(patchedTree[1].children[1].children[0]).toEqual([
507+
'slug',
508+
'original',
509+
'd',
510+
null,
511+
])
512+
expect(payload.q).toBe('?from=document')
513+
})
408514
})

packages/next/src/client/flight-data-helpers.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ import type {
1010
} from '../shared/lib/app-router-types'
1111
import { PAGE_SEGMENT_KEY } from '../shared/lib/segment'
1212
import type { NormalizedSearch } from './components/segment-cache/cache-key'
13+
import {
14+
NEXT_REWRITTEN_PATH_HEADER,
15+
NEXT_REWRITTEN_QUERY_HEADER,
16+
} from './components/app-router-headers'
1317
import {
1418
getCacheKeyForDynamicParam,
1519
parseDynamicParamFromURLPart,
@@ -95,10 +99,14 @@ export function createInitialRSCPayloadFromFallbackPrerender(
9599

96100
// Patch the Flight data sent by the server with the correct params parsed
97101
// from the URL + response object.
98-
const renderedPathname =
99-
renderedUrlOverride?.pathname ?? getRenderedPathname(response)
100-
const renderedSearch =
101-
renderedUrlOverride?.search ?? getRenderedSearch(response)
102+
const renderedPathname = response.headers.has(NEXT_REWRITTEN_PATH_HEADER)
103+
? getRenderedPathname(response)
104+
: ((renderedUrlOverride?.pathname ??
105+
getRenderedPathname(response)) as string)
106+
const renderedSearch = response.headers.has(NEXT_REWRITTEN_QUERY_HEADER)
107+
? getRenderedSearch(response)
108+
: ((renderedUrlOverride?.search ??
109+
getRenderedSearch(response)) as NormalizedSearch)
102110
const canonicalUrl = createHrefFromUrl(
103111
renderedUrlOverride ?? new URL(location.href)
104112
)

0 commit comments

Comments
 (0)