diff --git a/packages/next/src/build/adapter/build-complete.ts b/packages/next/src/build/adapter/build-complete.ts index f2c53d4e6275..29842f018d8d 100644 --- a/packages/next/src/build/adapter/build-complete.ts +++ b/packages/next/src/build/adapter/build-complete.ts @@ -1089,20 +1089,20 @@ export async function handleBuildComplete({ // Skip static metadata routes only when they are prerendered. // Dynamic metadata routes (e.g. robots/sitemap using connection()) // should remain app routes in adapter outputs. + // Only skip when the route has concrete prerenders we'll emit as + // static files below. Presence in `dynamicRoutes` only means a + // fallback pattern is registered — the function is still required + // as the parent for those dynamic-route entries. const isStaticMetadataRoute = isStaticMetadataFile(normalizedPage) const isPrerenderedMetadataRoute = prerenderManifest.routes[normalizedPage] || - prerenderManifest.dynamicRoutes[normalizedPage] || config.i18n?.locales?.some((locale) => { const localePathname = path.posix.join( '/', locale, normalizedPage.slice(1) ) - return ( - prerenderManifest.routes[localePathname] || - prerenderManifest.dynamicRoutes[localePathname] - ) + return prerenderManifest.routes[localePathname] }) if (isStaticMetadataRoute && isPrerenderedMetadataRoute) { diff --git a/test/e2e/app-dir/metadata-static-file-gsp/app/layout.tsx b/test/e2e/app-dir/metadata-static-file-gsp/app/layout.tsx new file mode 100644 index 000000000000..dbce4ea8e3ae --- /dev/null +++ b/test/e2e/app-dir/metadata-static-file-gsp/app/layout.tsx @@ -0,0 +1,11 @@ +export default function RootLayout({ + children, +}: { + children: React.ReactNode +}) { + return ( + +
{children} + + ) +} diff --git a/test/e2e/app-dir/metadata-static-file-gsp/app/results/[id]/opengraph-image.png b/test/e2e/app-dir/metadata-static-file-gsp/app/results/[id]/opengraph-image.png new file mode 100644 index 000000000000..aea7f5ff8ad3 Binary files /dev/null and b/test/e2e/app-dir/metadata-static-file-gsp/app/results/[id]/opengraph-image.png differ diff --git a/test/e2e/app-dir/metadata-static-file-gsp/app/results/[id]/page.tsx b/test/e2e/app-dir/metadata-static-file-gsp/app/results/[id]/page.tsx new file mode 100644 index 000000000000..4a83012671a1 --- /dev/null +++ b/test/e2e/app-dir/metadata-static-file-gsp/app/results/[id]/page.tsx @@ -0,0 +1,12 @@ +export function generateStaticParams() { + return [{ id: 'one' }, { id: 'two' }] +} + +export default async function Page({ + params, +}: { + params: Promise<{ id: string }> +}) { + const { id } = await params + returnresult: {id}
+} diff --git a/test/e2e/app-dir/metadata-static-file-gsp/metadata-static-file-gsp.test.ts b/test/e2e/app-dir/metadata-static-file-gsp/metadata-static-file-gsp.test.ts new file mode 100644 index 000000000000..c0b67b179deb --- /dev/null +++ b/test/e2e/app-dir/metadata-static-file-gsp/metadata-static-file-gsp.test.ts @@ -0,0 +1,15 @@ +import { nextTestSetup } from 'e2e-utils' + +describe('metadata-static-file-gsp', () => { + const { next, skipped } = nextTestSetup({ + files: __dirname, + }) + + if (skipped) { + return + } + + it('should build and serve a static metadata file colocated with generateStaticParams', async () => { + await next.render('/results/two') + }) +}) diff --git a/test/e2e/app-dir/metadata-static-file-gsp/next.config.js b/test/e2e/app-dir/metadata-static-file-gsp/next.config.js new file mode 100644 index 000000000000..807126e4cf0b --- /dev/null +++ b/test/e2e/app-dir/metadata-static-file-gsp/next.config.js @@ -0,0 +1,6 @@ +/** + * @type {import('next').NextConfig} + */ +const nextConfig = {} + +module.exports = nextConfig diff --git a/test/e2e/app-dir/metadata-static-file/metadata-static-file-dynamic-route.test.ts b/test/e2e/app-dir/metadata-static-file/metadata-static-file-dynamic-route.test.ts index ea1382c12ba9..d47e9ac5127f 100644 --- a/test/e2e/app-dir/metadata-static-file/metadata-static-file-dynamic-route.test.ts +++ b/test/e2e/app-dir/metadata-static-file/metadata-static-file-dynamic-route.test.ts @@ -2,20 +2,6 @@ import { nextTestSetup, isNextStart } from 'e2e-utils' import { getCommonMetadataHeadTags } from './utils' describe('metadata-files-static-output-dynamic-route', () => { - if (process.env.__NEXT_CACHE_COMPONENTS) { - // Cache Components build fails when metadata files are inside a dynamic route. - // - // Route "/dynamic/[id]" has a `generateMetadata` that depends on Request data (`cookies()`, etc...) - // or uncached external data (`fetch(...)`, etc...) when the rest of the route does not. - // See more info here: https://nextjs.org/docs/messages/next-prerender-dynamic-metadata - // Error occurred prerendering page "/dynamic/[id]". Read more: https://nextjs.org/docs/messages/prerender-error - // Export encountered an error on /dynamic/[id]/page: /dynamic/[id], exiting the build. - // - // TODO: Remove this skip when metadata files are supported in dynamic routes for Cache Components. - it.skip('should skip test for Cache Components', () => {}) - return - } - const { next, skipped } = nextTestSetup({ files: __dirname, skipDeployment: true,