Skip to content

Commit

Permalink
send initialCanonicalUrl in array format to prevent crawler confusion
Browse files Browse the repository at this point in the history
  • Loading branch information
ztanner committed Aug 30, 2024
1 parent 0e1bad0 commit a15901a
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 9 deletions.
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,
initialUrlParts,
initialSeedData,
couldBeIntercepted,
assetPrefix,
Expand All @@ -302,7 +302,7 @@ function Router({
createInitialRouterState({
buildId,
initialSeedData,
initialCanonicalUrl,
initialUrlParts,
initialTree,
initialParallelRoutes,
location: !isServer ? window.location : null,
Expand All @@ -312,7 +312,7 @@ function Router({
[
buildId,
initialSeedData,
initialCanonicalUrl,
initialUrlParts,
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,
initialUrlParts: 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,
initialUrlParts: 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
initialUrlParts: string[]
initialSeedData: CacheNodeSeedData
initialParallelRoutes: CacheNode['parallelRoutes']
location: Location | null
Expand All @@ -28,12 +28,16 @@ export function createInitialRouterState({
buildId,
initialTree,
initialSeedData,
initialCanonicalUrl,
initialUrlParts,
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 = initialUrlParts.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}
initialUrlParts={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}
initialUrlParts={prepareInitialCanonicalUrl(urlPathname)}
initialTree={initialTree}
initialHead={head}
globalErrorComponent={GlobalError}
Expand Down

0 comments on commit a15901a

Please sign in to comment.