From 16cc8e87b1369385e0feac140d1c65c17a770958 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Thu, 8 Jun 2023 15:55:28 +0200 Subject: [PATCH 1/6] Add unique search query for RSC requests to be cacable on CDN --- .../client/components/app-router-headers.ts | 2 ++ .../router-reducer/fetch-server-response.ts | 13 +++++++++++++ .../reducers/prefetch-reducer.ts | 3 +++ .../next/src/server/app-render/app-render.tsx | 1 + packages/next/src/server/base-server.ts | 1 + packages/next/src/server/internal-utils.ts | 2 ++ packages/next/src/server/request-meta.ts | 1 + packages/next/src/shared/lib/hash.ts | 4 ++++ .../app-dir/app-prefetch/prefetching.test.ts | 19 +++++++++++++++---- 9 files changed, 42 insertions(+), 4 deletions(-) diff --git a/packages/next/src/client/components/app-router-headers.ts b/packages/next/src/client/components/app-router-headers.ts index 0489abab5fdd..643531dbdd80 100644 --- a/packages/next/src/client/components/app-router-headers.ts +++ b/packages/next/src/client/components/app-router-headers.ts @@ -14,3 +14,5 @@ export const FLIGHT_PARAMETERS = [ [NEXT_ROUTER_STATE_TREE], [NEXT_ROUTER_PREFETCH], ] as const + +export const NEXT_RSC_UNION_QUERY = '__nextRSC' as const diff --git a/packages/next/src/client/components/router-reducer/fetch-server-response.ts b/packages/next/src/client/components/router-reducer/fetch-server-response.ts index 8028a8c46314..265658f4d8d6 100644 --- a/packages/next/src/client/components/router-reducer/fetch-server-response.ts +++ b/packages/next/src/client/components/router-reducer/fetch-server-response.ts @@ -10,6 +10,7 @@ import type { import { NEXT_ROUTER_PREFETCH, NEXT_ROUTER_STATE_TREE, + NEXT_RSC_UNION_QUERY, NEXT_URL, RSC, RSC_CONTENT_TYPE_HEADER, @@ -17,6 +18,7 @@ import { import { urlToUrlWithoutFlightMarker } from '../app-router' import { callServer } from '../../app-call-server' import { PrefetchKind } from './router-reducer-types' +import { hexHash } from '../../../shared/lib/hash' /** * Fetch the flight data for the provided url. Takes in the current router state to decide what to render server-side. @@ -56,6 +58,13 @@ export async function fetchServerResponse( headers[NEXT_URL] = nextUrl } + const uniqueCacheQuery = hexHash( + [ + headers[NEXT_ROUTER_PREFETCH] || '0', + headers[NEXT_ROUTER_STATE_TREE], + ].join(',') + ) + try { let fetchUrl = url if (process.env.NODE_ENV === 'production') { @@ -68,6 +77,10 @@ export async function fetchServerResponse( } } } + + // Add unique cache query to avoid caching conflicts on CDN which don't respect to Vary header + fetchUrl.searchParams.set(NEXT_RSC_UNION_QUERY, uniqueCacheQuery) + const res = await fetch(fetchUrl, { // Backwards compat for older browsers. `same-origin` is the default in modern browsers. credentials: 'same-origin', diff --git a/packages/next/src/client/components/router-reducer/reducers/prefetch-reducer.ts b/packages/next/src/client/components/router-reducer/reducers/prefetch-reducer.ts index 612ea7907b29..89a494675958 100644 --- a/packages/next/src/client/components/router-reducer/reducers/prefetch-reducer.ts +++ b/packages/next/src/client/components/router-reducer/reducers/prefetch-reducer.ts @@ -8,6 +8,7 @@ import { } from '../router-reducer-types' import { createRecordFromThenable } from '../create-record-from-thenable' import { prunePrefetchCache } from './prune-prefetch-cache' +import { NEXT_RSC_UNION_QUERY } from '../../app-router-headers' export function prefetchReducer( state: ReadonlyReducerState, @@ -17,6 +18,8 @@ export function prefetchReducer( prunePrefetchCache(state.prefetchCache) const { url } = action + url.searchParams.delete(NEXT_RSC_UNION_QUERY) + const href = createHrefFromUrl( url, // Ensures the hash is not part of the cache key as it does not affect fetching the server diff --git a/packages/next/src/server/app-render/app-render.tsx b/packages/next/src/server/app-render/app-render.tsx index a50cb0f3c101..ca3d9403ba5a 100644 --- a/packages/next/src/server/app-render/app-render.tsx +++ b/packages/next/src/server/app-render/app-render.tsx @@ -37,6 +37,7 @@ import { stripInternalQueries } from '../internal-utils' import { NEXT_ROUTER_PREFETCH, NEXT_ROUTER_STATE_TREE, + NEXT_RSC_UNION_QUERY, RSC, } from '../../client/components/app-router-headers' import { MetadataTree } from '../../lib/metadata/metadata' diff --git a/packages/next/src/server/base-server.ts b/packages/next/src/server/base-server.ts index 420798df42f0..43de6986b3a3 100644 --- a/packages/next/src/server/base-server.ts +++ b/packages/next/src/server/base-server.ts @@ -1351,6 +1351,7 @@ export default abstract class Server { return null } + delete query.__nextRSC delete query.__nextDataReq // normalize req.url for SSG paths as it is not exposed diff --git a/packages/next/src/server/internal-utils.ts b/packages/next/src/server/internal-utils.ts index e350fa2cb1b1..c6b7da650262 100644 --- a/packages/next/src/server/internal-utils.ts +++ b/packages/next/src/server/internal-utils.ts @@ -1,3 +1,4 @@ +import { NEXT_RSC_UNION_QUERY } from '../client/components/app-router-headers' import type { NextParsedUrlQuery } from './request-meta' const INTERNAL_QUERY_NAMES = [ @@ -6,6 +7,7 @@ const INTERNAL_QUERY_NAMES = [ '__nextInferredLocaleFromDefault', '__nextDefaultLocale', '__nextIsNotFound', + NEXT_RSC_UNION_QUERY, ] as const const EXTENDED_INTERNAL_QUERY_NAMES = ['__nextDataReq'] as const diff --git a/packages/next/src/server/request-meta.ts b/packages/next/src/server/request-meta.ts index c1fb5bcd6445..fd3cc6c2046b 100644 --- a/packages/next/src/server/request-meta.ts +++ b/packages/next/src/server/request-meta.ts @@ -97,6 +97,7 @@ type NextQueryMetadata = { _nextBubbleNoFallback?: '1' __nextDataReq?: '1' __nextCustomErrorRender?: '1' + __nextRSC?: string } export type NextParsedUrlQuery = ParsedUrlQuery & diff --git a/packages/next/src/shared/lib/hash.ts b/packages/next/src/shared/lib/hash.ts index aaaffdd50152..a5df303f523c 100644 --- a/packages/next/src/shared/lib/hash.ts +++ b/packages/next/src/shared/lib/hash.ts @@ -7,3 +7,7 @@ export function djb2Hash(str: string) { } return Math.abs(hash) } + +export function hexHash(str: string) { + return djb2Hash(str).toString(16).slice(0, 7) +} diff --git a/test/e2e/app-dir/app-prefetch/prefetching.test.ts b/test/e2e/app-dir/app-prefetch/prefetching.test.ts index 03b3020824bc..074f4884d666 100644 --- a/test/e2e/app-dir/app-prefetch/prefetching.test.ts +++ b/test/e2e/app-dir/app-prefetch/prefetching.test.ts @@ -85,8 +85,11 @@ createNextDescribe( await browser.eval( 'window.nd.router.prefetch("/static-page", {kind: "auto"})' ) + await check(() => { - return requests.some((req) => req.includes('static-page')) + return requests.some( + (req) => req.includes('static-page') && req.includes('__nextRSC=') + ) ? 'success' : JSON.stringify(requests) }, 'success') @@ -114,7 +117,9 @@ createNextDescribe( `window.nd.router.prefetch("/static-page", {kind: "auto"})` ) await check(() => { - return requests.some((req) => req.includes('static-page')) + return requests.some( + (req) => req.includes('static-page') && req.includes('__nextRSC=') + ) ? 'success' : JSON.stringify(requests) }, 'success') @@ -136,7 +141,10 @@ createNextDescribe( .waitForElementByCss('#static-page') expect( - requests.filter((request) => request === '/static-page').length + requests.filter( + (request) => + request === '/static-page' || request.includes('__nextRSC') + ).length ).toBe(1) }) @@ -159,7 +167,10 @@ createNextDescribe( for (let i = 0; i < 5; i++) { await waitFor(500) expect( - requests.filter((request) => request === '/static-page').length + requests.filter( + (request) => + request === '/static-page' || request.includes('__nextRSC') + ).length ).toBe(0) } }) From 38fca8cbdb68c8d07173181644937937d75362a5 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Thu, 8 Jun 2023 16:11:54 +0200 Subject: [PATCH 2/6] lint --- packages/next/src/server/app-render/app-render.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/next/src/server/app-render/app-render.tsx b/packages/next/src/server/app-render/app-render.tsx index ca3d9403ba5a..a50cb0f3c101 100644 --- a/packages/next/src/server/app-render/app-render.tsx +++ b/packages/next/src/server/app-render/app-render.tsx @@ -37,7 +37,6 @@ import { stripInternalQueries } from '../internal-utils' import { NEXT_ROUTER_PREFETCH, NEXT_ROUTER_STATE_TREE, - NEXT_RSC_UNION_QUERY, RSC, } from '../../client/components/app-router-headers' import { MetadataTree } from '../../lib/metadata/metadata' From 8ea30558ad43165f72522e43debc12f7aefbdea0 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Thu, 8 Jun 2023 18:19:07 +0200 Subject: [PATCH 3/6] strip query --- .../next/src/client/components/app-router.tsx | 2 ++ .../router-reducer/fetch-server-response.ts | 2 +- packages/next/src/server/base-server.ts | 2 ++ packages/next/src/server/internal-utils.ts | 22 ++++++++++--------- packages/next/src/server/next-server.ts | 2 ++ packages/next/src/server/web/adapter.ts | 10 ++++----- .../next/src/server/web/sandbox/sandbox.ts | 5 +++++ .../app-dir/app-prefetch/prefetching.test.ts | 4 ++-- 8 files changed, 31 insertions(+), 18 deletions(-) diff --git a/packages/next/src/client/components/app-router.tsx b/packages/next/src/client/components/app-router.tsx index 92d74b84a5a0..b2a3dd937801 100644 --- a/packages/next/src/client/components/app-router.tsx +++ b/packages/next/src/client/components/app-router.tsx @@ -49,6 +49,7 @@ import { RedirectBoundary } from './redirect-boundary' import { NotFoundBoundary } from './not-found-boundary' import { findHeadInCache } from './router-reducer/reducers/find-head-in-cache' import { createInfinitePromise } from './infinite-promise' +import { NEXT_RSC_UNION_QUERY } from './app-router-headers' const isServer = typeof window === 'undefined' @@ -65,6 +66,7 @@ export function getServerActionDispatcher() { export function urlToUrlWithoutFlightMarker(url: string): URL { const urlWithoutFlightParameters = new URL(url, location.origin) + urlWithoutFlightParameters.searchParams.delete(NEXT_RSC_UNION_QUERY) // TODO-APP: handle .rsc for static export case return urlWithoutFlightParameters } diff --git a/packages/next/src/client/components/router-reducer/fetch-server-response.ts b/packages/next/src/client/components/router-reducer/fetch-server-response.ts index 265658f4d8d6..7da0ffb0a71a 100644 --- a/packages/next/src/client/components/router-reducer/fetch-server-response.ts +++ b/packages/next/src/client/components/router-reducer/fetch-server-response.ts @@ -66,7 +66,7 @@ export async function fetchServerResponse( ) try { - let fetchUrl = url + let fetchUrl = new URL(url) if (process.env.NODE_ENV === 'production') { if (process.env.__NEXT_CONFIG_OUTPUT === 'export') { fetchUrl = new URL(url) // clone diff --git a/packages/next/src/server/base-server.ts b/packages/next/src/server/base-server.ts index 43de6986b3a3..fa7615743ba9 100644 --- a/packages/next/src/server/base-server.ts +++ b/packages/next/src/server/base-server.ts @@ -81,6 +81,7 @@ import { RSC, RSC_VARY_HEADER, FLIGHT_PARAMETERS, + NEXT_RSC_UNION_QUERY, } from '../client/components/app-router-headers' import { MatchOptions, @@ -2207,6 +2208,7 @@ export default abstract class Server { const { res, query, pathname } = ctx let page = pathname const bubbleNoFallback = !!query._nextBubbleNoFallback + delete query[NEXT_RSC_UNION_QUERY] delete query._nextBubbleNoFallback const options: MatchOptions = { diff --git a/packages/next/src/server/internal-utils.ts b/packages/next/src/server/internal-utils.ts index c6b7da650262..1ae559ea09db 100644 --- a/packages/next/src/server/internal-utils.ts +++ b/packages/next/src/server/internal-utils.ts @@ -10,7 +10,7 @@ const INTERNAL_QUERY_NAMES = [ NEXT_RSC_UNION_QUERY, ] as const -const EXTENDED_INTERNAL_QUERY_NAMES = ['__nextDataReq'] as const +const EDGE_EXTENDED_INTERNAL_QUERY_NAMES = ['__nextDataReq'] as const export function stripInternalQueries(query: NextParsedUrlQuery) { for (const name of INTERNAL_QUERY_NAMES) { @@ -18,19 +18,21 @@ export function stripInternalQueries(query: NextParsedUrlQuery) { } } -export function stripInternalSearchParams( - searchParams: URLSearchParams, - extended?: boolean -) { +export function stripInternalSearchParams( + url: T, + isEdge: boolean +): T { + const isStringUrl = typeof url === 'string' + const instance = isStringUrl ? new URL(url) : (url as URL) for (const name of INTERNAL_QUERY_NAMES) { - searchParams.delete(name) + instance.searchParams.delete(name) } - if (extended) { - for (const name of EXTENDED_INTERNAL_QUERY_NAMES) { - searchParams.delete(name) + if (isEdge) { + for (const name of EDGE_EXTENDED_INTERNAL_QUERY_NAMES) { + instance.searchParams.delete(name) } } - return searchParams + return (isStringUrl ? instance.toString() : instance) as T } diff --git a/packages/next/src/server/next-server.ts b/packages/next/src/server/next-server.ts index 67b9b5bbb8ba..b8f98de808e6 100644 --- a/packages/next/src/server/next-server.ts +++ b/packages/next/src/server/next-server.ts @@ -110,6 +110,7 @@ import { invokeRequest } from './lib/server-ipc/invoke-request' import { filterReqHeaders } from './lib/server-ipc/utils' import { createRequestResponseMocks } from './lib/mock-request' import chalk from 'next/dist/compiled/chalk' +import { NEXT_RSC_UNION_QUERY } from '../client/components/app-router-headers' export * from './base-server' @@ -1560,6 +1561,7 @@ export default class NextNodeServer extends BaseServer { return { finished: true } } delete query._nextBubbleNoFallback + delete query[NEXT_RSC_UNION_QUERY] const handledAsEdgeFunction = await this.runEdgeFunction({ req, diff --git a/packages/next/src/server/web/adapter.ts b/packages/next/src/server/web/adapter.ts index 85c05e0758a8..60c2abfcd5e5 100644 --- a/packages/next/src/server/web/adapter.ts +++ b/packages/next/src/server/web/adapter.ts @@ -117,14 +117,14 @@ export async function adapter( } } - // Strip internal query parameters off the request. - stripInternalSearchParams(requestUrl.searchParams, true) + const normalizeUrl = process.env.__NEXT_NO_MIDDLEWARE_URL_NORMALIZE + ? new URL(params.request.url) + : requestUrl const request = new NextRequestHint({ page: params.page, - input: process.env.__NEXT_NO_MIDDLEWARE_URL_NORMALIZE - ? params.request.url - : String(requestUrl), + // Strip internal query parameters off the request. + input: stripInternalSearchParams(normalizeUrl, true).toString(), init: { body: params.request.body, geo: params.request.geo, diff --git a/packages/next/src/server/web/sandbox/sandbox.ts b/packages/next/src/server/web/sandbox/sandbox.ts index 99693a4862bc..b894dc620720 100644 --- a/packages/next/src/server/web/sandbox/sandbox.ts +++ b/packages/next/src/server/web/sandbox/sandbox.ts @@ -4,6 +4,7 @@ import { getModuleContext } from './context' import { EdgeFunctionDefinition } from '../../../build/webpack/plugins/middleware-plugin' import { requestToBodyStream } from '../../body-streams' import type { EdgeRuntime } from 'next/dist/compiled/edge-runtime' +import { NEXT_RSC_UNION_QUERY } from '../../../client/components/app-router-headers' export const ErrorSource = Symbol('SandboxError') @@ -96,6 +97,10 @@ export const run = withTaggedErrors(async function runWithTaggedErrors(params) { : undefined const KUint8Array = runtime.evaluate('Uint8Array') + const urlInstance = new URL(params.request.url) + urlInstance.searchParams.delete(NEXT_RSC_UNION_QUERY) + + params.request.url = urlInstance.toString() try { const result = await edgeFunction({ diff --git a/test/e2e/app-dir/app-prefetch/prefetching.test.ts b/test/e2e/app-dir/app-prefetch/prefetching.test.ts index 074f4884d666..d91dfd845772 100644 --- a/test/e2e/app-dir/app-prefetch/prefetching.test.ts +++ b/test/e2e/app-dir/app-prefetch/prefetching.test.ts @@ -88,7 +88,7 @@ createNextDescribe( await check(() => { return requests.some( - (req) => req.includes('static-page') && req.includes('__nextRSC=') + (req) => req.includes('static-page') && !req.includes('__nextRSC') ) ? 'success' : JSON.stringify(requests) @@ -118,7 +118,7 @@ createNextDescribe( ) await check(() => { return requests.some( - (req) => req.includes('static-page') && req.includes('__nextRSC=') + (req) => req.includes('static-page') && !req.includes('__nextRSC') ) ? 'success' : JSON.stringify(requests) From 2baa0059ac49e6749d870ba4bb4ed453d1d47f47 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Fri, 9 Jun 2023 12:11:17 +0200 Subject: [PATCH 4/6] refactor and add more tests --- .../client/components/app-router-headers.ts | 2 +- .../next/src/client/components/app-router.tsx | 1 - .../router-reducer/fetch-server-response.ts | 1 - packages/next/src/server/base-server.ts | 2 +- packages/next/src/server/request-meta.ts | 3 ++- .../app-dir/app-prefetch/prefetching.test.ts | 18 ++++++++++++++---- .../navigation/app/assertion/page/page.js | 9 +++++++++ .../navigation/app/assertion/route/route.js | 8 ++++++++ test/e2e/app-dir/navigation/middleware.js | 13 +++++++++++++ 9 files changed, 48 insertions(+), 9 deletions(-) create mode 100644 test/e2e/app-dir/navigation/app/assertion/page/page.js create mode 100644 test/e2e/app-dir/navigation/app/assertion/route/route.js diff --git a/packages/next/src/client/components/app-router-headers.ts b/packages/next/src/client/components/app-router-headers.ts index 643531dbdd80..0ef9942f6b96 100644 --- a/packages/next/src/client/components/app-router-headers.ts +++ b/packages/next/src/client/components/app-router-headers.ts @@ -15,4 +15,4 @@ export const FLIGHT_PARAMETERS = [ [NEXT_ROUTER_PREFETCH], ] as const -export const NEXT_RSC_UNION_QUERY = '__nextRSC' as const +export const NEXT_RSC_UNION_QUERY = '_rsc' as const diff --git a/packages/next/src/client/components/app-router.tsx b/packages/next/src/client/components/app-router.tsx index b2a3dd937801..f8941503fbcb 100644 --- a/packages/next/src/client/components/app-router.tsx +++ b/packages/next/src/client/components/app-router.tsx @@ -67,7 +67,6 @@ export function getServerActionDispatcher() { export function urlToUrlWithoutFlightMarker(url: string): URL { const urlWithoutFlightParameters = new URL(url, location.origin) urlWithoutFlightParameters.searchParams.delete(NEXT_RSC_UNION_QUERY) - // TODO-APP: handle .rsc for static export case return urlWithoutFlightParameters } diff --git a/packages/next/src/client/components/router-reducer/fetch-server-response.ts b/packages/next/src/client/components/router-reducer/fetch-server-response.ts index 7da0ffb0a71a..7eb94ecd4cbe 100644 --- a/packages/next/src/client/components/router-reducer/fetch-server-response.ts +++ b/packages/next/src/client/components/router-reducer/fetch-server-response.ts @@ -69,7 +69,6 @@ export async function fetchServerResponse( let fetchUrl = new URL(url) if (process.env.NODE_ENV === 'production') { if (process.env.__NEXT_CONFIG_OUTPUT === 'export') { - fetchUrl = new URL(url) // clone if (fetchUrl.pathname.endsWith('/')) { fetchUrl.pathname += 'index.txt' } else { diff --git a/packages/next/src/server/base-server.ts b/packages/next/src/server/base-server.ts index fa7615743ba9..16824ab2e6f0 100644 --- a/packages/next/src/server/base-server.ts +++ b/packages/next/src/server/base-server.ts @@ -1352,7 +1352,7 @@ export default abstract class Server { return null } - delete query.__nextRSC + delete query[NEXT_RSC_UNION_QUERY] delete query.__nextDataReq // normalize req.url for SSG paths as it is not exposed diff --git a/packages/next/src/server/request-meta.ts b/packages/next/src/server/request-meta.ts index fd3cc6c2046b..8c9589a1b215 100644 --- a/packages/next/src/server/request-meta.ts +++ b/packages/next/src/server/request-meta.ts @@ -5,6 +5,7 @@ import type { UrlWithParsedQuery } from 'url' import type { BaseNextRequest } from './base-http' import type { CloneableBody } from './body-streams' import { RouteMatch } from './future/route-matches/route-match' +import { NEXT_RSC_UNION_QUERY } from '../client/components/app-router-headers' // FIXME: (wyattjoh) this is a temporary solution to allow us to pass data between bundled modules export const NEXT_REQUEST_META = Symbol.for('NextInternalRequestMeta') @@ -97,7 +98,7 @@ type NextQueryMetadata = { _nextBubbleNoFallback?: '1' __nextDataReq?: '1' __nextCustomErrorRender?: '1' - __nextRSC?: string + [NEXT_RSC_UNION_QUERY]?: string } export type NextParsedUrlQuery = ParsedUrlQuery & diff --git a/test/e2e/app-dir/app-prefetch/prefetching.test.ts b/test/e2e/app-dir/app-prefetch/prefetching.test.ts index d91dfd845772..d4941a5c95b0 100644 --- a/test/e2e/app-dir/app-prefetch/prefetching.test.ts +++ b/test/e2e/app-dir/app-prefetch/prefetching.test.ts @@ -1,6 +1,9 @@ import { createNextDescribe } from 'e2e-utils' import { check, waitFor } from 'next-test-utils' +// @ts-ignore +import { NEXT_RSC_UNION_QUERY } from 'next/dist/src/client/components/app-router-headers' + const browserConfigWithFixedTime = { beforePageLoad: (page) => { page.addInitScript(() => { @@ -38,6 +41,10 @@ createNextDescribe( return } + it('NEXT_RSC_UNION_QUERY query name is _rsc', async () => { + expect(NEXT_RSC_UNION_QUERY).toBe('_rsc') + }) + it('should show layout eagerly when prefetched with loading one level down', async () => { const browser = await next.browser('/', browserConfigWithFixedTime) // Ensure the page is prefetched @@ -88,7 +95,8 @@ createNextDescribe( await check(() => { return requests.some( - (req) => req.includes('static-page') && !req.includes('__nextRSC') + (req) => + req.includes('static-page') && !req.includes(NEXT_RSC_UNION_QUERY) ) ? 'success' : JSON.stringify(requests) @@ -118,7 +126,8 @@ createNextDescribe( ) await check(() => { return requests.some( - (req) => req.includes('static-page') && !req.includes('__nextRSC') + (req) => + req.includes('static-page') && !req.includes(NEXT_RSC_UNION_QUERY) ) ? 'success' : JSON.stringify(requests) @@ -143,7 +152,7 @@ createNextDescribe( expect( requests.filter( (request) => - request === '/static-page' || request.includes('__nextRSC') + request === '/static-page' || request.includes(NEXT_RSC_UNION_QUERY) ).length ).toBe(1) }) @@ -169,7 +178,8 @@ createNextDescribe( expect( requests.filter( (request) => - request === '/static-page' || request.includes('__nextRSC') + request === '/static-page' || + request.includes(NEXT_RSC_UNION_QUERY) ).length ).toBe(0) } diff --git a/test/e2e/app-dir/navigation/app/assertion/page/page.js b/test/e2e/app-dir/navigation/app/assertion/page/page.js new file mode 100644 index 000000000000..4fcd943b6a29 --- /dev/null +++ b/test/e2e/app-dir/navigation/app/assertion/page/page.js @@ -0,0 +1,9 @@ +import { strict as assert } from 'node:assert' +// @ts-ignore +import { NEXT_RSC_UNION_QUERY } from 'next/dist/client/components/app-router-headers' + +export default function Page({ searchParams }) { + assert(searchParams[NEXT_RSC_UNION_QUERY] === undefined) + + return

no rsc query page

+} diff --git a/test/e2e/app-dir/navigation/app/assertion/route/route.js b/test/e2e/app-dir/navigation/app/assertion/route/route.js new file mode 100644 index 000000000000..30a15365067a --- /dev/null +++ b/test/e2e/app-dir/navigation/app/assertion/route/route.js @@ -0,0 +1,8 @@ +import { strict as assert } from 'node:assert' +// @ts-ignore +import { NEXT_RSC_UNION_QUERY } from 'next/dist/client/components/app-router-headers' + +export function GET(request) { + assert(request.nextUrl.searchParams.get(NEXT_RSC_UNION_QUERY) === null) + return new Response('no rsc query route') +} diff --git a/test/e2e/app-dir/navigation/middleware.js b/test/e2e/app-dir/navigation/middleware.js index 7c0cde52e966..21f6b424c308 100644 --- a/test/e2e/app-dir/navigation/middleware.js +++ b/test/e2e/app-dir/navigation/middleware.js @@ -1,11 +1,24 @@ // @ts-check import { NextResponse } from 'next/server' +// @ts-ignore +import { NEXT_RSC_UNION_QUERY } from 'next/dist/client/components/app-router-headers' + +if (NEXT_RSC_UNION_QUERY !== '_rsc') { + throw new Error(`NEXT_RSC_UNION_QUERY should be _rsc`) +} /** * @param {import('next/server').NextRequest} request * @returns {NextResponse | undefined} */ export function middleware(request) { + const rscQuery = request.nextUrl.searchParams.get(NEXT_RSC_UNION_QUERY) + + // Test that the RSC query is not present in the middleware + if (rscQuery) { + throw new Error('RSC query should not be present in the middleware') + } + if (request.nextUrl.pathname === '/redirect-middleware-to-dashboard') { return NextResponse.redirect(new URL('/redirect-dest', request.url)) } From 65220a3806a46925c60d8e41192387e5ab202e86 Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Fri, 9 Jun 2023 14:48:40 +0200 Subject: [PATCH 5/6] rm --- packages/next/src/server/base-server.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/next/src/server/base-server.ts b/packages/next/src/server/base-server.ts index 16824ab2e6f0..5f49de31169f 100644 --- a/packages/next/src/server/base-server.ts +++ b/packages/next/src/server/base-server.ts @@ -1352,7 +1352,6 @@ export default abstract class Server { return null } - delete query[NEXT_RSC_UNION_QUERY] delete query.__nextDataReq // normalize req.url for SSG paths as it is not exposed From 600c013d0ef1ea5cab74f9fd75ef36d3d375808d Mon Sep 17 00:00:00 2001 From: Jiachi Liu Date: Fri, 9 Jun 2023 15:07:17 +0200 Subject: [PATCH 6/6] fix test --- test/e2e/app-dir/app-prefetch/prefetching.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/app-dir/app-prefetch/prefetching.test.ts b/test/e2e/app-dir/app-prefetch/prefetching.test.ts index d4941a5c95b0..189d27acc6f6 100644 --- a/test/e2e/app-dir/app-prefetch/prefetching.test.ts +++ b/test/e2e/app-dir/app-prefetch/prefetching.test.ts @@ -2,7 +2,7 @@ import { createNextDescribe } from 'e2e-utils' import { check, waitFor } from 'next-test-utils' // @ts-ignore -import { NEXT_RSC_UNION_QUERY } from 'next/dist/src/client/components/app-router-headers' +import { NEXT_RSC_UNION_QUERY } from 'next/dist/client/components/app-router-headers' const browserConfigWithFixedTime = { beforePageLoad: (page) => {