Skip to content

Commit

Permalink
Add warning for missing metadataBase in social images (#49180)
Browse files Browse the repository at this point in the history
We picked `VERCEL_URL` env for `metadataBase` in preview mode, but also picking that on production, this could potentially use the unique build url for social images if you didn't set `metadataBase`

We recommend to set the major/preferred domain to `metadataBase` if you're using social images, this PR help warn you in every env if you're missing that

[slack thread](https://vercel.slack.com/archives/C03KAR5DCKC/p1683150633962539?thread_ts=1683144147.664059&cid=C03KAR5DCKC)
  • Loading branch information
huozhi committed May 4, 2023
1 parent 11f2fd4 commit 7fd97b8
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 10 deletions.
6 changes: 3 additions & 3 deletions packages/next/src/lib/metadata/resolvers/resolve-opengraph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type { FieldResolverWithMetadataBase } from '../types/resolvers'
import type { ResolvedTwitterMetadata, Twitter } from '../types/twitter-types'
import { resolveAsArrayOrUndefined } from '../generate/utils'
import {
getFallbackMetadataBaseIfPresent,
getSocialImageFallbackMetadataBase,
isStringOrURL,
resolveUrl,
} from './resolve-url'
Expand Down Expand Up @@ -101,7 +101,7 @@ export const resolveOpenGraph: FieldResolverWithMetadataBase<'openGraph'> = (
}
}

const imageMetadataBase = getFallbackMetadataBaseIfPresent(metadataBase)
const imageMetadataBase = getSocialImageFallbackMetadataBase(metadataBase)
resolved.images = resolveImages(og.images, imageMetadataBase)
}

Expand Down Expand Up @@ -132,7 +132,7 @@ export const resolveTwitter: FieldResolverWithMetadataBase<'twitter'> = (
for (const infoKey of TwitterBasicInfoKeys) {
resolved[infoKey] = twitter[infoKey] || null
}
const imageMetadataBase = getFallbackMetadataBaseIfPresent(metadataBase)
const imageMetadataBase = getSocialImageFallbackMetadataBase(metadataBase)
resolved.images = resolveImages(twitter.images, imageMetadataBase)

if ('card' in resolved) {
Expand Down
30 changes: 23 additions & 7 deletions packages/next/src/lib/metadata/resolvers/resolve-url.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import path from '../../../shared/lib/isomorphic/path'
import * as Log from '../../../build/output/log'

function isStringOrURL(icon: any): icon is string | URL {
return typeof icon === 'string' || icon instanceof URL
Expand All @@ -10,20 +11,35 @@ function createLocalMetadataBase() {

// For deployment url for metadata routes, prefer to use the deployment url if possible
// as these routes are unique to the deployments url.
export function getFallbackMetadataBaseIfPresent(
export function getSocialImageFallbackMetadataBase(
metadataBase: URL | null
): URL | null {
const isMetadataBaseMissing = !metadataBase
const defaultMetadataBase = createLocalMetadataBase()
const deploymentUrl =
process.env.VERCEL_URL && new URL(`https://${process.env.VERCEL_URL}`)

let fallbackMetadata
if (process.env.NODE_ENV === 'development') {
return defaultMetadataBase
fallbackMetadata = defaultMetadataBase
} else {
fallbackMetadata =
process.env.NODE_ENV === 'production' &&
deploymentUrl &&
process.env.VERCEL_ENV === 'preview'
? deploymentUrl
: metadataBase || deploymentUrl || defaultMetadataBase
}

if (isMetadataBaseMissing) {
// Add new line to warning for worker output
console.log()
Log.warnOnce(
`metadata.metadataBase is not set for resolving social open graph or twitter images, fallbacks to "${fallbackMetadata.origin}". See https://beta.nextjs.org/docs/api-reference/metadata#metadatabase`
)
}
return process.env.NODE_ENV === 'production' &&
deploymentUrl &&
process.env.VERCEL_ENV === 'preview'
? deploymentUrl
: metadataBase || deploymentUrl || defaultMetadataBase

return fallbackMetadata
}

function resolveUrl(url: null | undefined, metadataBase: URL | null): null
Expand Down
8 changes: 8 additions & 0 deletions test/e2e/app-dir/metadata-missing-metadata-base/app/layout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export default function Layout({ children }) {
return (
<html>
<head></head>
<body>{children}</body>
</html>
)
}
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions test/e2e/app-dir/metadata-missing-metadata-base/app/page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from 'react'

export default function Page() {
return <>hello index</>
}

export const metadata = {
title: 'index page',
}
31 changes: 31 additions & 0 deletions test/e2e/app-dir/metadata-missing-metadata-base/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { createNext, FileRef } from 'e2e-utils'
import { NextInstance } from 'test/lib/next-modes/base'
import { fetchViaHTTP } from 'next-test-utils'

describe('app dir - metadata missing metadataBase', () => {
let next: NextInstance

if ((global as any).isNextDeploy) {
return it('should skip for deploy', () => {})
}

beforeAll(async () => {
next = await createNext({
skipStart: true,
files: new FileRef(__dirname),
})
})
afterAll(() => next.destroy())

it('should fallback to localhost if metadataBase is missing for absolute urls resolving', async () => {
await next.start()
await fetchViaHTTP(next.url, '/')
expect(next.cliOutput).toInclude(
'metadata.metadataBase is not set for resolving social open graph or twitter images, fallbacks to'
)
expect(next.cliOutput).toInclude('"http://localhost:')
expect(next.cliOutput).toInclude(
'. See https://beta.nextjs.org/docs/api-reference/metadata#metadatabase'
)
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
experimental: { appDir: true },
}

0 comments on commit 7fd97b8

Please sign in to comment.