SEO
使用查询字符串的 SEO 陷阱和最佳实践
如果您的页面使用查询字符串仅用于本地状态,您应该为页面添加一个规范 URL,以告知 SEO 爬虫忽略查询字符串并在没有它的情况下索引页面。
在 Next.js app router 中,这是通过 metadata 对象完成的:
import type { Metadata } from 'next'
export const metadata: Metadata = {
alternates: {
canonical: '/url/path/without/querystring'
}
}然而,如果查询字符串定义了页面显示的内容(例如:YouTube 的 watch URL,如 https://www.youtube.com/watch?v=dQw4w9WgXcQ),您的规范 URL 应该包含相关的查询字符串,并且您仍然可以使用您的解析器来读取它,并序列化规范 URL。
import type { Metadata, ResolvingMetadata } from 'next'
import { notFound } from "next/navigation";
import {
createParser,
parseAsString,
createLoader,
createSerializer,
type SearchParams,
type UrlKeys
} from 'nuqs/server'
const youTubeVideoIdRegex = /^[^"&?\/\s]{11}$/i
const youTubeSearchParams = {
videoId: createParser({
parse(query) {
if (!youTubeVideoIdRegex.test(query)) {
return null
}
return query
},
serialize(videoId) {
return videoId
}
})
}
const youTubeUrlKeys: UrlKeys<typeof youTubeSearchParams> = {
videoId: 'v'
}
const loadYouTubeSearchParams = createLoader(
youTubeSearchParams,
{
urlKeys: youTubeUrlKeys
}
)
const serializeYouTubeSearchParams = createSerializer(
youTubeSearchParams,
{
urlKeys: youTubeUrlKeys
}
)
// --
type Props = {
searchParams: Promise<SearchParams>
}
export async function generateMetadata({
searchParams
}: Props): Promise<Metadata> {
const { videoId } = await loadYouTubeSearchParams(searchParams)
if (!videoId) {
notFound()
}
return {
alternates: {
canonical: serializeYouTubeSearchParams('/watch', { videoId })
// /watch?v=dQw4w9WgXcQ
}
}
}