File tree Expand file tree Collapse file tree 5 files changed +96
-3
lines changed
packages/next/src/build/templates
test/e2e/app-dir/cache-components-bot-ua Expand file tree Collapse file tree 5 files changed +96
-3
lines changed Original file line number Diff line number Diff line change @@ -653,11 +653,13 @@ export async function handler(
653
653
fallbackMode = parseFallbackField ( prerenderInfo . fallback )
654
654
}
655
655
656
- // When serving a bot request, we want to serve a blocking render and not
657
- // the prerendered page. This ensures that the correct content is served
656
+ // When serving a HTML bot request, we want to serve a blocking render and
657
+ // not the prerendered page. This ensures that the correct content is served
658
658
// to the bot in the head.
659
659
if ( fallbackMode === FallbackMode . PRERENDER && isBot ( userAgent ) ) {
660
- fallbackMode = FallbackMode . BLOCKING_STATIC_RENDER
660
+ if ( ! isRoutePPREnabled || isHtmlBot ) {
661
+ fallbackMode = FallbackMode . BLOCKING_STATIC_RENDER
662
+ }
661
663
}
662
664
663
665
if ( previousCacheEntry ?. isStale === - 1 ) {
Original file line number Diff line number Diff line change
1
+ import React from 'react'
2
+
3
+ import type { Metadata } from 'next'
4
+
5
+ export async function generateMetadata ( ) : Promise < Metadata > {
6
+ await new Promise ( ( resolve ) => setTimeout ( resolve , 1000 ) ) // Simulate a delay
7
+ return {
8
+ title : 'Home' ,
9
+ description : 'Welcome to the home page' ,
10
+ }
11
+ }
12
+
13
+ export default async function Home ( {
14
+ params,
15
+ } : {
16
+ params : Promise < { slug : string } >
17
+ } ) {
18
+ const { slug } = await params
19
+ // Math.random() will cause SSG_BAILOUT if static generation runs
20
+ // Bots should bypass static generation in PPR to avoid this error
21
+ const randomValue = Math . random ( )
22
+
23
+ return (
24
+ < >
25
+ < h1 > { slug } </ h1 >
26
+ < p > { randomValue } </ p >
27
+ </ >
28
+ )
29
+ }
Original file line number Diff line number Diff line change
1
+ import React , { Suspense } from 'react'
2
+ import type { Metadata } from 'next'
3
+
4
+ export const metadata : Metadata = {
5
+ title : 'PPR Bot SSG Bypass Test' ,
6
+ description :
7
+ 'Test bot static generation bypass with PPR and cache components' ,
8
+ }
9
+
10
+ export default function RootLayout ( {
11
+ children,
12
+ } : {
13
+ children : React . ReactNode
14
+ } ) {
15
+ return (
16
+ < html lang = "en" >
17
+ < body >
18
+ < Suspense > { children } </ Suspense >
19
+ </ body >
20
+ </ html >
21
+ )
22
+ }
Original file line number Diff line number Diff line change
1
+ import { nextTestSetup } from 'e2e-utils'
2
+
3
+ describe ( 'cache-components PPR bot static generation bypass' , ( ) => {
4
+ const { next } = nextTestSetup ( {
5
+ files : __dirname ,
6
+ } )
7
+
8
+ it ( 'should bypass static generation for DOM bot requests to avoid SSG_BAILOUT' , async ( ) => {
9
+ const res = await next . fetch ( '/foo' , {
10
+ headers : {
11
+ 'user-agent' : 'Googlebot' ,
12
+ } ,
13
+ } )
14
+ // With cache components + PPR enabled, DOM bots should behave like regular users
15
+ // and use the fallback cache mechanism. This allows them to handle dynamic content
16
+ // like Math.random() without triggering SSG_BAILOUT errors.
17
+ expect ( res . status ) . toBe ( 200 )
18
+
19
+ // Verify that the response contains the page content
20
+ const html = await res . text ( )
21
+
22
+ // Check that the page rendered successfully
23
+ // With PPR, content is streamed via script tags
24
+ expect ( html ) . toContain ( '\\"children\\":\\"foo\\"' )
25
+
26
+ // Verify Math.random() was executed (check for a decimal number in the streamed content)
27
+ expect ( html ) . toMatch ( / \\ " c h i l d r e n \\ " : 0 \. \d + / )
28
+
29
+ // With PPR, content is streamed, but the important thing is that
30
+ // the page rendered without a 500 error
31
+ } )
32
+ } )
Original file line number Diff line number Diff line change
1
+ /** @type {import('next').NextConfig } */
2
+ const nextConfig = {
3
+ experimental : {
4
+ cacheComponents : true ,
5
+ } ,
6
+ }
7
+
8
+ module . exports = nextConfig
You can’t perform that action at this time.
0 commit comments