Skip to content

Commit

Permalink
Improve error for missing default export in dynamic metadata routes (#…
Browse files Browse the repository at this point in the history
…57711)

Displaying hints of "missing default export" if you didn't properly export the `default` handler for og image 

```
   ▲ Next.js 14.0.1-canary.2
   - Local:        http://localhost:3000

 ✓ Ready in 1089ms
 ✓ Compiled /opengraph-image/[[...__metadata_id__]]/route in 211ms (44 modules)
 ⨯ Error: Default export is missing in "/Users/huozhi/workspace/next.js/test/e2e/app-dir/metadata-dynam
ic-routes/app/opengraph-image.tsx"
    at eval (webpack:///app/opengraph-image.tsx?3407:11:1)
    at (app-metadata-route)/../../../../packages/next/dist/build/webpack/loaders/next-metadata-route-lo
ader.js?page=%2Fopengraph-image%2F%5B%5B...__metadata_id__%5D%5D%2Froute&isDynamic=1!./app/opengraph-im
age.tsx?__next_metadata_route__ (/Users/huozhi/workspace/next.js/test/e2e/app-dir/metadata-dynamic-rout
es/.next/server/app/opengraph-image/[[...__metadata_id__]]/route.js:362:1)
    at __webpack_require__ (/Users/huozhi/workspace/next.js/test/e2e/app-dir/metadata-dynamic-routes/.n
ext/server/webpack-runtime.js:33:42)
```
  • Loading branch information
huozhi authored Oct 30, 2023
1 parent a07e0de commit 3553c65
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ import fs from 'fs'
import path from 'path'
import { imageExtMimeTypeMap } from '../../../lib/mime-type'

function errorOnBadHandler(resourcePath: string) {
return `
if (typeof handler !== 'function') {
throw new Error('Default export is missing in ${JSON.stringify(
resourcePath
)}')
}
`
}

const cacheHeader = {
none: 'no-cache, no-store',
longCache: 'public, immutable, no-transform, max-age=31536000',
Expand Down Expand Up @@ -78,6 +88,8 @@ import { resolveRouteData } from 'next/dist/build/webpack/loaders/metadata/resol
const contentType = ${JSON.stringify(getContentType(resourcePath))}
const fileType = ${JSON.stringify(getFilenameAndExtension(resourcePath).name)}
${errorOnBadHandler(resourcePath)}
export async function GET() {
const data = await handler()
const content = resolveRouteData(data, fileType)
Expand All @@ -103,6 +115,8 @@ const imageModule = { ...userland }
const handler = imageModule.default
const generateImageMetadata = imageModule.generateImageMetadata
${errorOnBadHandler(resourcePath)}
export async function GET(_, ctx) {
const { __metadata_id__ = [], ...params } = ctx.params || {}
const targetId = __metadata_id__[0]
Expand Down Expand Up @@ -160,6 +174,8 @@ const generateSitemaps = sitemapModule.generateSitemaps
const contentType = ${JSON.stringify(getContentType(resourcePath))}
const fileType = ${JSON.stringify(getFilenameAndExtension(resourcePath).name)}
${errorOnBadHandler(resourcePath)}
${'' /* re-export the userland route configs */}
export * from ${JSON.stringify(resourcePath)}
Expand Down
27 changes: 27 additions & 0 deletions test/e2e/app-dir/metadata-dynamic-routes/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,33 @@ createNextDescribe(
await next.fetch('/metadata-base/unset/sitemap.xml/0')
}
})

it('should error if the default export of dynamic image is missing', async () => {
const ogImageFilePath = 'app/opengraph-image.tsx'
const ogImageFileContent = await next.readFile(ogImageFilePath)
const ogImageFileContentWithoutDefaultExport =
ogImageFileContent.replace(
'export default function',
'export function'
)

try {
await next.patchFile(
ogImageFilePath,
ogImageFileContentWithoutDefaultExport
)
const currentNextCliOutputLength = next.cliOutput.length

await check(async () => {
await next.fetch('/opengraph-image')
const output = next.cliOutput.slice(currentNextCliOutputLength)
expect(output).toContain(`Default export is missing in`)
return 'success'
}, /success/)
} finally {
await next.patchFile(ogImageFilePath, ogImageFileContent)
}
})
}

if (isNextStart) {
Expand Down

0 comments on commit 3553c65

Please sign in to comment.