Next.js页面meta标签无法被爬虫抓取的问题求助
问题解决:Next.js页面Meta标签无法被爬虫识别
问题背景
使用Next.js + TypeStack开发,通过MongoDB获取数据,浏览器开发者工具中能正常看到页面的title和meta描述,但Bing搜索引擎检测提示标题和Meta描述标签缺失,问题根源在于当前采用的客户端数据获取方式。
核心原因
当前代码用useEffect + axios做客户端渲染,数据获取和Meta标签渲染都依赖客户端JS执行。但绝大多数搜索引擎爬虫(包括Bing的URL检测工具)不会执行页面JS,只会抓取服务器返回的初始HTML内容——初始HTML里没有Meta标签,自然被判定为缺失。
解决方案
改用Next.js提供的**服务端渲染(SSR)或静态站点生成(SSG)**方案,在服务器端提前获取数据并渲染出包含完整Meta标签的HTML,确保爬虫能直接抓取到所需内容。
方案1:使用getServerSideProps(服务端渲染)
适合内容频繁更新的场景,每次请求都会在服务器端获取最新数据并渲染页面。
修改[pid].tsx代码如下:
import React from 'react' import { useRouter } from 'next/router'; import Head from 'next/head'; import Navbar from '@/sections/Navbar'; import BlogBody from '@/sections/BlogBody'; import Footer from '@/sections/Footer'; import { IBlog } from '@/schema/blogSchema'; import Error from '@/components/Error'; import Loading from '@/components/Loading'; // 直接在服务端调用数据库查询逻辑,无需通过客户端API import { searchExactBlog } from '@/services/blogService'; interface BlogProps { currentDoc: IBlog | null; isError: boolean; } const Blog = ({ currentDoc, isError }: BlogProps) => { const _router = useRouter(); // 路由过渡阶段显示加载 if (_router.isFallback) { return <Loading />; } return ( <> <Head> <title>{currentDoc ? `${currentDoc.title} - Wayne Blogs` : 'Wayne Blogs'}</title> <meta name="description" content={currentDoc?.desc || 'Wayne Blogs - 分享技术与思考'} /> <meta name="author" content={currentDoc?.author || 'Wayne'} /> <link rel="shortcut icon" href="/favicon.svg" type="image/x-icon" /> </Head> <Navbar /> <main> {isError ? ( <Error text="获取文章失败,请刷新页面重试" /> ) : currentDoc ? ( <BlogBody blogInfo={currentDoc} /> ) : ( <Error text="该文章不存在" /> )} <Footer /> </main> </> ) } // 服务端数据获取逻辑 export async function getServerSideProps(context: any) { const { pid } = context.params; let currentDoc: IBlog | null = null; let isError = false; try { const result = await searchExactBlog(pid); currentDoc = result.data[0] || null; } catch (err) { isError = true; } return { props: { currentDoc, isError } } } export default Blog
方案2:使用getStaticProps + getStaticPaths(静态站点生成)
适合内容不频繁更新的博客场景,提前生成静态页面,性能更优。
修改[pid].tsx代码如下:
import React from 'react' import Head from 'next/head'; import Navbar from '@/sections/Navbar'; import BlogBody from '@/sections/BlogBody'; import Footer from '@/sections/Footer'; import { IBlog } from '@/schema/blogSchema'; import Error from '@/components/Error'; import { getAllBlogIds, getBlogById } from '@/services/blogService'; interface BlogProps { currentDoc: IBlog; } const Blog = ({ currentDoc }: BlogProps) => { return ( <> <Head> <title>{`${currentDoc.title} - Wayne Blogs`}</title> <meta name="description" content={currentDoc.desc} /> <meta name="author" content={currentDoc.author} /> <link rel="shortcut icon" href="/favicon.svg" type="image/x-icon" /> </Head> <Navbar /> <main> <BlogBody blogInfo={currentDoc} /> <Footer /> </main> </> ) } // 获取所有需要静态生成的博客ID export async function getStaticPaths() { const paths = await getAllBlogIds(); // 返回格式:[{ params: { pid: 'blog-1' } }, ...] return { paths, fallback: 'blocking' // 未提前生成的页面会在首次请求时自动生成 } } // 根据ID获取数据并生成静态页面 export async function getStaticProps(context: any) { const { pid } = context.params; const currentDoc = await getBlogById(pid); // 文章不存在则返回404 if (!currentDoc) { return { notFound: true } } return { props: { currentDoc }, revalidate: 86400 // 每天自动重新生成页面,更新内容 } } export default Blog
关键注意事项
- 禁止在客户端通过
useEffect获取数据后渲染Meta标签,爬虫无法识别这类动态添加的内容。 - 服务端获取数据时,直接调用数据库查询逻辑,无需通过客户端API请求,减少网络开销。
- 使用服务端/静态生成方案时,组件直接接收服务端传递的props,无需再用
useState管理数据状态。
内容的提问来源于stack exchange,提问作者Ali Wayne
相关产品推荐
相关产品推荐

