Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

backport: send initialCanonicalUrl in array format to prevent crawler confusion #69509

Merged
merged 1 commit into from
Aug 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions packages/next/src/client/components/app-router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ function Router({
buildId,
initialHead,
initialTree,
initialCanonicalUrl,
urlParts,
initialSeedData,
couldBeIntercepted,
assetPrefix,
Expand All @@ -302,7 +302,7 @@ function Router({
createInitialRouterState({
buildId,
initialSeedData,
initialCanonicalUrl,
urlParts,
initialTree,
initialParallelRoutes,
location: !isServer ? window.location : null,
Expand All @@ -312,7 +312,7 @@ function Router({
[
buildId,
initialSeedData,
initialCanonicalUrl,
urlParts,
initialTree,
initialHead,
couldBeIntercepted,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ describe('createInitialRouterState', () => {
const state = createInitialRouterState({
buildId,
initialTree,
initialCanonicalUrl,
urlParts: initialCanonicalUrl.split('/'),
initialSeedData: ['', {}, children, null],
initialParallelRoutes,
location: new URL('/linking', 'https://localhost') as any,
Expand All @@ -47,7 +47,7 @@ describe('createInitialRouterState', () => {
const state2 = createInitialRouterState({
buildId,
initialTree,
initialCanonicalUrl,
urlParts: initialCanonicalUrl.split('/'),
initialSeedData: ['', {}, children, null],
initialParallelRoutes,
location: new URL('/linking', 'https://localhost') as any,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { addRefreshMarkerToActiveParallelSegments } from './refetch-inactive-par
export interface InitialRouterStateParameters {
buildId: string
initialTree: FlightRouterState
initialCanonicalUrl: string
urlParts: string[]
initialSeedData: CacheNodeSeedData
initialParallelRoutes: CacheNode['parallelRoutes']
location: Location | null
Expand All @@ -28,12 +28,16 @@ export function createInitialRouterState({
buildId,
initialTree,
initialSeedData,
initialCanonicalUrl,
urlParts,
initialParallelRoutes,
location,
initialHead,
couldBeIntercepted,
}: InitialRouterStateParameters) {
// When initialized on the server, the canonical URL is provided as an array of parts.
// This is to ensure that when the RSC payload streamed to the client, crawlers don't interpret it
// as a URL that should be crawled.
const initialCanonicalUrl = urlParts.join('/')
const isServer = !location
const rsc = initialSeedData[2]

Expand Down
15 changes: 13 additions & 2 deletions packages/next/src/server/app-render/app-render.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,17 @@ type ReactServerAppProps = {
ctx: AppRenderContext
asNotFound: boolean
}

/**
* Crawlers will inadvertently think the canonicalUrl in the RSC payload should be crawled
* when our intention is to just seed the router state with the current URL.
* This function splits up the pathname so that we can later join it on
* when we're ready to consume the path.
*/
function prepareInitialCanonicalUrl(pathname: string) {
return pathname.split('/')
}

// This is the root component that runs in the RSC context
async function ReactServerApp({ tree, ctx, asNotFound }: ReactServerAppProps) {
// Create full component tree from root to leaf.
Expand Down Expand Up @@ -461,7 +472,7 @@ async function ReactServerApp({ tree, ctx, asNotFound }: ReactServerAppProps) {
<AppRouter
buildId={ctx.renderOpts.buildId}
assetPrefix={ctx.assetPrefix}
initialCanonicalUrl={urlPathname}
urlParts={prepareInitialCanonicalUrl(urlPathname)}
// This is the router state tree.
initialTree={initialTree}
// This is the tree of React nodes that are seeded into the cache
Expand Down Expand Up @@ -549,7 +560,7 @@ async function ReactServerError({
<AppRouter
buildId={ctx.renderOpts.buildId}
assetPrefix={ctx.assetPrefix}
initialCanonicalUrl={urlPathname}
urlParts={prepareInitialCanonicalUrl(urlPathname)}
initialTree={initialTree}
initialHead={head}
globalErrorComponent={GlobalError}
Expand Down
Loading