Skip to content

Commit

Permalink
Fix: strip _rsc query for client navigation rsc request (#65084)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
huozhi committed Apr 28, 2024
1 parent 3f907d3 commit b9c98a8
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 11 deletions.
4 changes: 2 additions & 2 deletions packages/next/src/build/swc/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1338,15 +1338,15 @@ 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
} catch (e) {}
} 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) {}
}
Expand Down
11 changes: 10 additions & 1 deletion packages/next/src/lib/url.ts
Original file line number Diff line number Diff line change
@@ -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)
Expand All @@ -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
}
18 changes: 14 additions & 4 deletions packages/next/src/server/next-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'

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

Expand Down Expand Up @@ -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)
Expand Down
6 changes: 6 additions & 0 deletions test/e2e/app-dir/logging/app/headers/page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { headers } from 'next/headers'

export default function Page() {
headers()
return <p>{'headers()'}</p>
}
24 changes: 23 additions & 1 deletion test/e2e/app-dir/logging/app/layout.js
Original file line number Diff line number Diff line change
@@ -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>
)
}
6 changes: 5 additions & 1 deletion test/e2e/app-dir/logging/app/link/page.js
Original file line number Diff line number Diff line change
@@ -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>
)
}
18 changes: 16 additions & 2 deletions test/e2e/app-dir/logging/fetch-logging.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit b9c98a8

Please sign in to comment.