Skip to content

Commit

Permalink
Respect reexports from metadata API routes (#70508)
Browse files Browse the repository at this point in the history
  • Loading branch information
huozhi authored Sep 26, 2024
1 parent 154dd24 commit 3ed9f4b
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,27 @@ function errorOnBadHandler(resourcePath: string) {
`
}

/* re-export the userland route configs */
async function createReExportsCode(
resourcePath: string,
loaderContext: webpack.LoaderContext<any>
) {
const exportNames = await getLoaderModuleNamedExports(
resourcePath,
loaderContext
)
// Re-export configs but avoid conflicted exports
const reExportNames = exportNames.filter(
(name) => name !== 'default' && name !== 'generateSitemaps'
)

return reExportNames.length > 0
? `export { ${reExportNames.join(', ')} } from ${JSON.stringify(
resourcePath
)}\n`
: ''
}

const cacheHeader = {
none: 'no-cache, no-store',
longCache: 'public, immutable, no-transform, max-age=31536000',
Expand Down Expand Up @@ -85,7 +106,10 @@ export const dynamic = 'force-static'
return code
}

function getDynamicTextRouteCode(resourcePath: string) {
async function getDynamicTextRouteCode(
resourcePath: string,
loaderContext: webpack.LoaderContext<any>
) {
return `\
/* dynamic asset route */
import { NextResponse } from 'next/server'
Expand All @@ -96,6 +120,7 @@ const contentType = ${JSON.stringify(getContentType(resourcePath))}
const fileType = ${JSON.stringify(getFilenameAndExtension(resourcePath).name)}
${errorOnBadHandler(resourcePath)}
${await createReExportsCode(resourcePath, loaderContext)}
export async function GET() {
const data = await handler()
Expand All @@ -112,7 +137,10 @@ export async function GET() {
}

// <metadata-image>/[id]/route.js
function getDynamicImageRouteCode(resourcePath: string) {
async function getDynamicImageRouteCode(
resourcePath: string,
loaderContext: webpack.LoaderContext<any>
) {
return `\
/* dynamic image route */
import { NextResponse } from 'next/server'
Expand All @@ -124,6 +152,7 @@ const handler = imageModule.default
const generateImageMetadata = imageModule.generateImageMetadata
${errorOnBadHandler(resourcePath)}
${await createReExportsCode(resourcePath, loaderContext)}
export async function GET(_, ctx) {
const { __metadata_id__, ...params } = ctx.params || {}
Expand Down Expand Up @@ -162,10 +191,6 @@ async function getDynamicSitemapRouteCode(
resourcePath,
loaderContext
)
// Re-export configs but avoid conflicted exports
const reExportNames = exportNames.filter(
(name) => name !== 'default' && name !== 'generateSitemaps'
)

const hasGenerateSitemaps = exportNames.includes('generateSitemaps')

Expand Down Expand Up @@ -195,15 +220,7 @@ const contentType = ${JSON.stringify(getContentType(resourcePath))}
const fileType = ${JSON.stringify(getFilenameAndExtension(resourcePath).name)}
${errorOnBadHandler(resourcePath)}
${'' /* re-export the userland route configs */}
${
reExportNames.length > 0
? `export { ${reExportNames.join(', ')} } from ${JSON.stringify(
resourcePath
)}\n`
: ''
}
${await createReExportsCode(resourcePath, loaderContext)}
export async function GET(_, ctx) {
const { __metadata_id__: id, ...params } = ctx.params || {}
Expand Down Expand Up @@ -253,11 +270,11 @@ const nextMetadataRouterLoader: webpack.LoaderDefinitionFunction<MetadataRouteLo
let code = ''
if (isDynamicRouteExtension === '1') {
if (fileBaseName === 'robots' || fileBaseName === 'manifest') {
code = getDynamicTextRouteCode(filePath)
code = await getDynamicTextRouteCode(filePath, this)
} else if (fileBaseName === 'sitemap') {
code = await getDynamicSitemapRouteCode(filePath, this)
} else {
code = getDynamicImageRouteCode(filePath)
code = await getDynamicImageRouteCode(filePath, this)
}
} else {
code = await getStaticAssetRouteCode(filePath, fileBaseName)
Expand Down
22 changes: 22 additions & 0 deletions test/production/app-dir/metadata-revalidate/app/manifest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { MetadataRoute } from 'next'

export default function manifest(): MetadataRoute.Manifest {
return {
name: 'Next.js App',
short_name: 'Next.js App',
description: 'Next.js App',
start_url: '/',
display: 'standalone',
background_color: '#fff',
theme_color: '#fff',
icons: [
{
src: '/favicon.ico',
sizes: 'any',
type: 'image/x-icon',
},
],
}
}

export const revalidate = 5
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { ImageResponse } from 'next/og'

/* without generateImageMetadata */
export default function og() {
return new ImageResponse(
(
<div
style={{
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: 128,
background: 'lavender',
}}
>
Open Graph
</div>
)
)
}

export const revalidate = 5
14 changes: 14 additions & 0 deletions test/production/app-dir/metadata-revalidate/app/robots.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { MetadataRoute } from 'next'

export default function robots(): MetadataRoute.Robots {
return {
rules: {
userAgent: '*',
allow: '/',
disallow: '/private/',
},
sitemap: 'https://acme.com/sitemap.xml',
}
}

export const revalidate = 5
12 changes: 12 additions & 0 deletions test/production/app-dir/metadata-revalidate/app/sitemap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export default function sitemap() {
return [
{
url: 'https://acme.com',
lastModified: new Date(),
changeFrequency: 'yearly',
priority: 1,
},
]
}

export const revalidate = 5
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { nextTestSetup } from 'e2e-utils'

describe('app-dir - metadata-revalidate', () => {
const { next } = nextTestSetup({
files: __dirname,
})

it('should contain the routes in prerender manifest', async () => {
const manifestContent = await next.readFile('.next/prerender-manifest.json')
const prerenderManifest = JSON.parse(manifestContent)

expect(
prerenderManifest.routes['/revalidate/og/opengraph-image']
.initialRevalidateSeconds
).toBe(5)
expect(
prerenderManifest.routes['/manifest.webmanifest'].initialRevalidateSeconds
).toBe(5)
expect(
prerenderManifest.routes['/robots.txt'].initialRevalidateSeconds
).toBe(5)
expect(
prerenderManifest.routes['/sitemap.xml'].initialRevalidateSeconds
).toBe(5)
})
})
9 changes: 9 additions & 0 deletions test/turbopack-build-tests-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -16302,6 +16302,15 @@
"flakey": [],
"runtimeError": false
},
"test/production/app-dir/metadata-revalidate/metadata-revalidate.test.ts": {
"passed": [],
"failed": [
"app-dir - metadata-revalidate should contain the routes in prerender manifest"
],
"pending": [],
"flakey": [],
"runtimeError": false
},
"test/production/middleware-typescript/test/index.test.ts": {
"passed": ["middleware-typescript should have built and started"],
"failed": [],
Expand Down

0 comments on commit 3ed9f4b

Please sign in to comment.