mirror of
https://github.com/vercel/commerce.git
synced 2025-07-23 04:36:49 +00:00
feat: replace next-seo with custom solution (#660)
* replace next-seo with custom solution * Updated check Co-authored-by: LFades <luis@vercel.com>
This commit is contained in:
157
site/components/common/SEO/SEO.tsx
Normal file
157
site/components/common/SEO/SEO.tsx
Normal file
@@ -0,0 +1,157 @@
|
||||
import Head from 'next/head'
|
||||
import { FC, Fragment, ReactNode } from 'react'
|
||||
import config from '@config/seo_meta.json'
|
||||
|
||||
const storeUrl =
|
||||
process.env.NEXT_PUBLIC_STORE_URL || process.env.NEXT_PUBLIC_VERCEL_URL
|
||||
const storeBaseUrl = storeUrl ? `https://${storeUrl}` : null
|
||||
|
||||
interface OgImage {
|
||||
url?: string
|
||||
width?: string
|
||||
height?: string
|
||||
alt?: string
|
||||
}
|
||||
|
||||
interface Props {
|
||||
title?: string
|
||||
description?: string
|
||||
robots?: string
|
||||
openGraph?: {
|
||||
title?: string
|
||||
type?: string
|
||||
locale?: string
|
||||
description?: string
|
||||
site_name?: string
|
||||
url?: string
|
||||
images?: OgImage[]
|
||||
}
|
||||
children?: ReactNode
|
||||
}
|
||||
|
||||
const ogImage = ({ url, width, height, alt }: OgImage, index: number) => {
|
||||
// generate full URL for OG image url with store base URL
|
||||
const imgUrl = storeBaseUrl ? new URL(url!, storeBaseUrl).toString() : url
|
||||
return (
|
||||
<Fragment key={`og:image:${index}`}>
|
||||
<meta
|
||||
key={`og:image:url:${index}`}
|
||||
property="og:image"
|
||||
content={imgUrl}
|
||||
/>
|
||||
<meta
|
||||
key={`og:image:width:${index}`}
|
||||
property="og:image:width"
|
||||
content={width}
|
||||
/>
|
||||
<meta
|
||||
key={`og:image:height:${index}`}
|
||||
property="og:image:height"
|
||||
content={height}
|
||||
/>
|
||||
<meta
|
||||
key={`og:image:alt:${index}`}
|
||||
property="og:image:alt"
|
||||
content={alt}
|
||||
/>
|
||||
</Fragment>
|
||||
)
|
||||
}
|
||||
|
||||
const SEO: FC<Props> = ({
|
||||
title,
|
||||
description,
|
||||
openGraph,
|
||||
robots,
|
||||
children,
|
||||
}) => {
|
||||
/**
|
||||
* @see https://nextjs.org/docs/api-reference/next/head
|
||||
*
|
||||
* meta or any other elements need to be contained as direct children of the Head element,
|
||||
* or wrapped into maximum one level of <React.Fragment> or arrays
|
||||
* otherwise the tags won't be correctly picked up on client-side navigations.
|
||||
*
|
||||
* The `key` property makes the tag is only rendered once,
|
||||
*/
|
||||
return (
|
||||
<Head>
|
||||
<title key="title">
|
||||
{title ? `${config.titleTemplate.replace(/%s/g, title)}` : config.title}
|
||||
</title>
|
||||
<meta
|
||||
key="description"
|
||||
name="description"
|
||||
content={description || config.description}
|
||||
/>
|
||||
<meta
|
||||
key="og:type"
|
||||
property="og:type"
|
||||
content={openGraph?.type ?? config.openGraph.type}
|
||||
/>
|
||||
<meta
|
||||
key="og:title"
|
||||
property="og:title"
|
||||
content={
|
||||
openGraph?.title ?? config.openGraph.title ?? title ?? config.title
|
||||
}
|
||||
/>
|
||||
<meta
|
||||
key="og:description"
|
||||
property="og:description"
|
||||
content={
|
||||
openGraph?.description ??
|
||||
config.openGraph.description ??
|
||||
description ??
|
||||
config.description
|
||||
}
|
||||
/>
|
||||
<meta
|
||||
key="og:site_name"
|
||||
property="og:site_name"
|
||||
content={openGraph?.site_name ?? config.openGraph.site_name}
|
||||
/>
|
||||
<meta
|
||||
key="og:url"
|
||||
property="og:url"
|
||||
content={openGraph?.url ?? config.openGraph.url}
|
||||
></meta>
|
||||
{openGraph?.locale && (
|
||||
<meta key="og:locale" property="og:locale" content={openGraph.locale} />
|
||||
)}
|
||||
{openGraph?.images?.length
|
||||
? openGraph.images.map((img, index) => ogImage(img, index))
|
||||
: ogImage(config.openGraph.images[0], 0)}
|
||||
{config.twitter.cardType && (
|
||||
<meta
|
||||
key="twitter:card"
|
||||
name="twitter:card"
|
||||
content={config.twitter.cardType}
|
||||
/>
|
||||
)}
|
||||
{config.twitter.site && (
|
||||
<meta
|
||||
key="twitter:site"
|
||||
name="twitter:site"
|
||||
content={config.twitter.site}
|
||||
/>
|
||||
)}
|
||||
{config.twitter.handle && (
|
||||
<meta
|
||||
key="twitter:creator"
|
||||
name="twitter:creator"
|
||||
content={config.twitter.handle}
|
||||
/>
|
||||
)}
|
||||
<meta key="robots" name="robots" content={robots ?? 'index,follow'} />
|
||||
<meta
|
||||
key="googlebot"
|
||||
name="googlebot"
|
||||
content={robots ?? 'index,follow'}
|
||||
></meta>
|
||||
{children}
|
||||
</Head>
|
||||
)
|
||||
}
|
||||
|
||||
export default SEO
|
1
site/components/common/SEO/index.ts
Normal file
1
site/components/common/SEO/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { default } from './SEO'
|
Reference in New Issue
Block a user