Fix: strip _rsc query for client navigation rsc request (#65084)

When you do client navigation to a dynamic page with call like
`headers()`, it wil send RSC request for that page. We want to skip the
`_rsc` query in the logging as it's disruptive.

Closes NEXT-3077
Closes #64355
This commit is contained in:
Jiachi Liu 2024-04-28 22:15:38 +02:00 committed by GitHub
parent 3f907d38cb
commit b9c98a8866
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 76 additions and 11 deletions

View file

@ -1338,7 +1338,7 @@ function loadNative(importPath?: string) {
try {
// Use the binary directly to skip `pnpm pack` for testing as it's slow because of the large native binary.
bindings = require(`${NEXT_TEST_NATIVE_DIR}/next-swc.${triple.platformArchABI}.node`)
console.log(
infoLog(
'next-swc build: local built @next/swc from NEXT_TEST_NATIVE_DIR'
)
break
@ -1346,7 +1346,7 @@ function loadNative(importPath?: string) {
} else {
try {
bindings = require(`@next/swc/native/next-swc.${triple.platformArchABI}.node`)
console.log('next-swc build: local built @next/swc')
infoLog('next-swc build: local built @next/swc')
break
} catch (e) {}
}

View file

@ -1,4 +1,6 @@
const DUMMY_ORIGIN = 'http://n'
import { NEXT_RSC_UNION_QUERY } from '../client/components/app-router-headers'
export const DUMMY_ORIGIN = 'http://n'
function getUrlWithoutHost(url: string) {
return new URL(url, DUMMY_ORIGIN)
@ -11,3 +13,10 @@ export function getPathname(url: string) {
export function isFullStringUrl(url: string) {
return /https?:\/\//.test(url)
}
export function stripNextRscUnionQuery(relativeUrl: string): string {
const urlInstance = new URL(relativeUrl, DUMMY_ORIGIN)
urlInstance.searchParams.delete(NEXT_RSC_UNION_QUERY)
return urlInstance.pathname + urlInstance.search
}

View file

@ -104,6 +104,7 @@ import { interopDefault } from '../lib/interop-default'
import { formatDynamicImportPath } from '../lib/format-dynamic-import-path'
import type { NextFontManifest } from '../build/webpack/plugins/next-font-manifest-plugin'
import { isInterceptionRouteRewrite } from '../lib/generate-interception-routes-rewrites'
import { stripNextRscUnionQuery } from '../lib/url'
export * from './base-server'
@ -1123,9 +1124,9 @@ export default class NextNodeServer extends BaseServer<
// we don't log for non-route requests
const routeMatch = getRequestMeta(req).match
const isRSC = isRSCRequestCheck(normalizedReq)
if (!routeMatch || isRSC || isMiddlewareRequest) return
if (!routeMatch || isMiddlewareRequest) return
const isRSC = isRSCRequestCheck(normalizedReq)
const reqEnd = Date.now()
const fetchMetrics = normalizedReq.fetchMetrics || []
const reqDuration = reqEnd - reqStart
@ -1140,9 +1141,14 @@ export default class NextNodeServer extends BaseServer<
const color = statusColor(res.statusCode)
const method = req.method || 'GET'
const requestUrl = req.url || ''
const loggingUrl = isRSC
? stripNextRscUnionQuery(requestUrl)
: requestUrl
writeStdoutLine(
`${method} ${req.url ?? ''} ${color(
(res.statusCode ?? 200).toString()
`${method} ${loggingUrl} ${color(
res.statusCode.toString()
)} in ${reqDuration}ms`
)
@ -1798,6 +1804,10 @@ export default class NextNodeServer extends BaseServer<
? `https://${req.headers.host || 'localhost'}${req.url}`
: req.url
const isRSC = isRSCRequestCheck(req)
if (isRSC) {
addRequestMeta(req, 'isRSCRequest', true)
}
addRequestMeta(req, 'initURL', initUrl)
addRequestMeta(req, 'initQuery', { ...parsedUrl.query })
addRequestMeta(req, 'initProtocol', protocol)

View file

@ -0,0 +1,6 @@
import { headers } from 'next/headers'
export default function Page() {
headers()
return <p>{'headers()'}</p>
}

View file

@ -1,7 +1,29 @@
import Link from 'next/link'
export default function Layout({ children }) {
return (
<html>
<body>{children}</body>
<body>
<header>
<Link id="nav-link" href={'/link'}>
/link
</Link>
<br />
<Link id="nav-headers" href={'/headers'}>
/headers
</Link>
<br />
<Link id="nav-default-cache" href={'/default-cache'}>
/default-cache
</Link>
<br />
<Link id="nav-cache-revalidate" href={'/cache-revalidate'}>
/cache-revalidate
</Link>
<br />
</header>
<div>{children}</div>
</body>
</html>
)
}

View file

@ -1,5 +1,9 @@
import Link from 'next/link'
export default function Page() {
return <Link href="/foo">Trigger RSC request</Link>
return (
<Link id="foo" href="/foo">
Trigger RSC request
</Link>
)
}

View file

@ -167,16 +167,30 @@ describe('app-dir - logging', () => {
})
})
it('should exlucde Middleware invoked and _rsc requests', async () => {
it('should exclude Middleware invoked and _rsc requests', async () => {
const outputIndex = next.cliOutput.length
const browser = await next.browser('/link')
await browser.elementByCss('a').click()
await browser.elementByCss('a#foo').click()
await browser.waitForElementByCss('h2')
const logs = stripAnsi(next.cliOutput.slice(outputIndex))
expect(logs).not.toContain('/_next/static')
expect(logs).not.toContain('?_rsc')
})
it('should not log _rsc query for client navigation RSC request', async () => {
const outputIndex = next.cliOutput.length
const browser = await next.browser('/')
await browser.elementByCss('a#nav-headers').click()
await browser.waitForElementByCss('p')
const logs = stripAnsi(next.cliOutput.slice(outputIndex))
expect(logs).toContain('GET /')
expect(logs).toContain('GET /headers')
expect(logs).not.toContain('/_next/static')
expect(logs).not.toContain('?_rsc')
})
}
} else {
// No fetches logging enabled