mirror of
https://github.com/hanzoai/next.js.git
synced 2026-09-24 17:00:51 +00:00
Fix: Do not force BLOCKING_STATIC_RENDER for DOM bots (#82427)
The issue was that DOM bots with PPR-enabled routes were being forced to use BLOCKING_STATIC_RENDER mode, which prevented them from using the fallback cache lookup mechanism. This caused them to generate new content with isRevalidating: true, which blocks postponed data and triggers the Math.random() static generation bailout error. For HTML bots, they keep using BLOCKING_STATIC_RENDER because SSG was turned off for them and won't see the SSG bailout error. For DOM bots, they should behave like a normal user. Fixes NAR-273
This commit is contained in:
@@ -653,11 +653,13 @@ export async function handler(
|
||||
fallbackMode = parseFallbackField(prerenderInfo.fallback)
|
||||
}
|
||||
|
||||
// When serving a bot request, we want to serve a blocking render and not
|
||||
// the prerendered page. This ensures that the correct content is served
|
||||
// When serving a HTML bot request, we want to serve a blocking render and
|
||||
// not the prerendered page. This ensures that the correct content is served
|
||||
// to the bot in the head.
|
||||
if (fallbackMode === FallbackMode.PRERENDER && isBot(userAgent)) {
|
||||
fallbackMode = FallbackMode.BLOCKING_STATIC_RENDER
|
||||
if (!isRoutePPREnabled || isHtmlBot) {
|
||||
fallbackMode = FallbackMode.BLOCKING_STATIC_RENDER
|
||||
}
|
||||
}
|
||||
|
||||
if (previousCacheEntry?.isStale === -1) {
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import React from 'react'
|
||||
|
||||
import type { Metadata } from 'next'
|
||||
|
||||
export async function generateMetadata(): Promise<Metadata> {
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000)) // Simulate a delay
|
||||
return {
|
||||
title: 'Home',
|
||||
description: 'Welcome to the home page',
|
||||
}
|
||||
}
|
||||
|
||||
export default async function Home({
|
||||
params,
|
||||
}: {
|
||||
params: Promise<{ slug: string }>
|
||||
}) {
|
||||
const { slug } = await params
|
||||
// Math.random() will cause SSG_BAILOUT if static generation runs
|
||||
// Bots should bypass static generation in PPR to avoid this error
|
||||
const randomValue = Math.random()
|
||||
|
||||
return (
|
||||
<>
|
||||
<h1>{slug}</h1>
|
||||
<p>{randomValue}</p>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import React, { Suspense } from 'react'
|
||||
import type { Metadata } from 'next'
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: 'PPR Bot SSG Bypass Test',
|
||||
description:
|
||||
'Test bot static generation bypass with PPR and cache components',
|
||||
}
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body>
|
||||
<Suspense>{children}</Suspense>
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import { nextTestSetup } from 'e2e-utils'
|
||||
|
||||
describe('cache-components PPR bot static generation bypass', () => {
|
||||
const { next } = nextTestSetup({
|
||||
files: __dirname,
|
||||
})
|
||||
|
||||
it('should bypass static generation for DOM bot requests to avoid SSG_BAILOUT', async () => {
|
||||
const res = await next.fetch('/foo', {
|
||||
headers: {
|
||||
'user-agent': 'Googlebot',
|
||||
},
|
||||
})
|
||||
// With cache components + PPR enabled, DOM bots should behave like regular users
|
||||
// and use the fallback cache mechanism. This allows them to handle dynamic content
|
||||
// like Math.random() without triggering SSG_BAILOUT errors.
|
||||
expect(res.status).toBe(200)
|
||||
|
||||
// Verify that the response contains the page content
|
||||
const html = await res.text()
|
||||
|
||||
// Check that the page rendered successfully
|
||||
// With PPR, content is streamed via script tags
|
||||
expect(html).toContain('\\"children\\":\\"foo\\"')
|
||||
|
||||
// Verify Math.random() was executed (check for a decimal number in the streamed content)
|
||||
expect(html).toMatch(/\\"children\\":0\.\d+/)
|
||||
|
||||
// With PPR, content is streamed, but the important thing is that
|
||||
// the page rendered without a 500 error
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,8 @@
|
||||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
experimental: {
|
||||
cacheComponents: true,
|
||||
},
|
||||
}
|
||||
|
||||
module.exports = nextConfig
|
||||
Reference in New Issue
Block a user