Skip to content

Commit

Permalink
Use vercel deployment url for metadataBase fallbacks (#65089)
Browse files Browse the repository at this point in the history
Leveraging the system env vars for fallback logic

x-ref:
https://vercel.com/docs/projects/environment-variables/system-environment-variables

For preview deployment: prefer using `VERCEL_BRANCH_URL`, fallback to
`VERCEL_URL`
For production deployment: prefer using `VERCEL_PROJECT_PRODUCTION_URL`

Closes NEXT-3237
  • Loading branch information
huozhi authored Apr 29, 2024
1 parent b04cc93 commit 1df2f3e
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 6 deletions.
76 changes: 75 additions & 1 deletion packages/next/src/lib/metadata/resolvers/resolve-url.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { resolveUrl, resolveAbsoluteUrlWithPathname } from './resolve-url'
import {
resolveUrl,
resolveAbsoluteUrlWithPathname,
getSocialImageFallbackMetadataBase,
} from './resolve-url'

// required to be resolved as URL with resolveUrl()
describe('metadata: resolveUrl', () => {
Expand Down Expand Up @@ -106,3 +110,73 @@ describe('resolveAbsoluteUrlWithPathname', () => {
})
})
})

describe('getSocialImageFallbackMetadataBase', () => {
describe('fallbackMetadataBase when metadataBase is not present', () => {
let originalEnv: NodeJS.ProcessEnv
function getSocialImageFallbackMetadataBaseHelper(): string {
return getSocialImageFallbackMetadataBase(null).fallbackMetadataBase.href
}

beforeEach(() => {
originalEnv = process.env
})

afterEach(() => {
delete process.env.VERCEL_URL
delete process.env.VERCEL_ENV
delete process.env.VERCEL_BRANCH_URL
delete process.env.VERCEL_PROJECT_PRODUCTION_URL

process.env = originalEnv
})

it('should return localhost url in local dev mode', () => {
// @ts-expect-error override process env
process.env.NODE_ENV = 'development'
expect(getSocialImageFallbackMetadataBaseHelper()).toBe(
'http://localhost:3000/'
)
})

it('should return local url in local build mode', () => {
// @ts-expect-error override process env
process.env.NODE_ENV = 'production'
expect(getSocialImageFallbackMetadataBaseHelper()).toBe(
'http://localhost:3000/'
)
})

it('should prefer branch url in preview deployment if presents', () => {
// @ts-expect-error override process env
process.env.NODE_ENV = 'production'
process.env.VERCEL_ENV = 'preview'
process.env.VERCEL_BRANCH_URL = 'branch-url'
process.env.VERCEL_URL = 'vercel-url'
expect(getSocialImageFallbackMetadataBaseHelper()).toBe(
'https://branch-url/'
)
})

it('should return vercel url in preview deployment if only it presents', () => {
// @ts-expect-error override process env
process.env.NODE_ENV = 'production'
process.env.VERCEL_ENV = 'preview'
process.env.VERCEL_URL = 'vercel-url'
expect(getSocialImageFallbackMetadataBaseHelper()).toBe(
'https://vercel-url/'
)
})

it('should return project production url in production deployment', () => {
// @ts-expect-error override process env
process.env.NODE_ENV = 'production'
process.env.VERCEL_ENV = 'production'
process.env.VERCEL_URL = 'vercel-url'
process.env.VERCEL_PROJECT_PRODUCTION_URL = 'production-url'
expect(getSocialImageFallbackMetadataBaseHelper()).toBe(
'https://production-url/'
)
})
})
})
20 changes: 15 additions & 5 deletions packages/next/src/lib/metadata/resolvers/resolve-url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@ function createLocalMetadataBase() {
return new URL(`http://localhost:${process.env.PORT || 3000}`)
}

function getPreviewDeploymentUrl(): URL | undefined {
const origin = process.env.VERCEL_BRANCH_URL || process.env.VERCEL_URL
return origin ? new URL(`https://${origin}`) : undefined
}

function getProductionDeploymentUrl(): URL | undefined {
const origin = process.env.VERCEL_PROJECT_PRODUCTION_URL
return origin ? new URL(`https://${origin}`) : undefined
}

// 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 getSocialImageFallbackMetadataBase(metadataBase: URL | null): {
Expand All @@ -17,19 +27,19 @@ export function getSocialImageFallbackMetadataBase(metadataBase: URL | null): {
} {
const isMetadataBaseMissing = !metadataBase
const defaultMetadataBase = createLocalMetadataBase()
const deploymentUrl =
process.env.VERCEL_URL && new URL(`https://${process.env.VERCEL_URL}`)
const previewDeploymentUrl = getPreviewDeploymentUrl()
const productionDeploymentUrl = getProductionDeploymentUrl()

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

return {
Expand Down

0 comments on commit 1df2f3e

Please sign in to comment.