在无头WordPress+WPGraphQL+Next.js中用Yoast获取页面元数据
解决无头WordPress中Next.js获取静态页面Yoast SEO元数据的问题
问题梳理
已实现博客文章的Yoast SEO元数据动态获取,但首页、关于页、联系页这类静态页面仍在手动配置标题、描述,尝试编写的WPGraphQL查询和Next.js代码未生效。
错误点分析
从你提供的代码来看,主要问题有:
getStaticProps中把查询返回的page数据赋值给了post变量,但组件接收的props是page,导致组件内无法获取到数据- WPGraphQL查询未请求
seo.fullHead字段,但组件中尝试解析page.seo.fullHead,会引发报错 - 静态页面的查询变量硬编码为
contact,无法适配不同页面的动态需求 NextSeo配置仍为硬编码,未使用从WordPress获取的元数据
解决方案
方案1:单个页面单独处理(如首页、关于页)
以首页(pages/index.js)为例,直接查询首页的SEO数据:
import { NextSeo } from "next-seo"; import Head from "next/head"; import parse from "html-react-parser"; import { client } from "../lib/apollo"; import { gql } from "@apollo/client"; import Layout from "../components/Layout"; export default function Home({ page }) { const fullHead = parse(page.seo.fullHead); return ( <> <Head> <link rel="icon" href="/favicon.svg" /> {fullHead} </Head> <NextSeo title={page.seo.title} description={page.seo.metaDesc} openGraph={{ url: page.seo.canonical, title: page.seo.title, description: page.seo.metaDesc, images: [ { url: "https://url.com/images/logo.svg", width: 800, height: 600, alt: "x x Logo", }, ], site_name: "x x", }} /> <Layout> {/* 页面内容 */} </Layout> </> ); } export async function getStaticProps() { const GET_HOME_PAGE = gql` query GetHomePage { page(id: "/", idType: URI) { seo { metaDesc title canonical fullHead } } } `; const response = await client.query({ query: GET_HOME_PAGE }); const page = response?.data?.page; return { props: { page }, // 可选:设置重验证时间,自动更新数据 revalidate: 60, }; }
关于页(pages/about.js)只需要修改查询中的id为"/about"即可。
方案2:动态路由处理所有静态页面
创建pages/[pageSlug].jsx,通过动态路由匹配所有静态页面,自动获取对应SEO数据:
import { NextSeo } from "next-seo"; import Head from "next/head"; import parse from "html-react-parser"; import { client } from "../lib/apollo"; import { gql } from "@apollo/client"; import Layout from "../components/Layout"; import { useRouter } from "next/router"; export default function StaticPage({ page }) { const router = useRouter(); if (router.isFallback) return <div>加载中...</div>; const fullHead = parse(page.seo.fullHead); return ( <> <Head> <link rel="icon" href="/favicon.svg" /> {fullHead} </Head> <NextSeo title={page.seo.title} description={page.seo.metaDesc} openGraph={{ url: page.seo.canonical, title: page.seo.title, description: page.seo.metaDesc, images: [ { url: "https://url.com/images/logo.svg", width: 800, height: 600, alt: "x x Logo", }, ], site_name: "x x", }} /> <Layout> {/* 渲染页面内容,比如page.content */} {parse(page.content)} </Layout> </> ); } export async function getStaticProps({ params }) { const GET_STATIC_PAGE = gql` query GetStaticPage($slug: ID!) { page(id: $slug, idType: URI) { title content seo { metaDesc title canonical fullHead } } } `; // 处理首页:当slug为空时,URI为"/" const pageUri = params.pageSlug ? `/${params.pageSlug}` : "/"; const response = await client.query({ query: GET_STATIC_PAGE, variables: { slug: pageUri }, }); const page = response?.data?.page; return { props: { page }, revalidate: 60, }; } export async function getStaticPaths() { // 先查询所有静态页面的slug,生成预渲染路径 const GET_ALL_PAGES = gql` query GetAllPages { pages { nodes { uri } } } `; const response = await client.query({ query: GET_ALL_PAGES }); const pages = response?.data?.pages?.nodes || []; const paths = pages.map((page) => ({ params: { pageSlug: page.uri.replace("/", "") || "" }, })); return { paths, fallback: "blocking", }; }
关键注意事项
- 确保WPGraphQL Yoast SEO插件已正确安装并激活,否则无法获取
seo字段 - 查询时必须包含需要用到的所有字段(如
fullHead、metaDesc等),避免因字段缺失报错 - 使用
revalidate可以实现静态页面的增量更新,无需重新构建整个项目
内容的提问来源于stack exchange,提问作者Laicus
相关产品推荐
相关产品推荐

