Gatsby动态页面数据获取疑难:getServerData与GraphQL变量传递
Gatsby + GraphQL 动态页面与数据查询解决方案
核心结论
- 通过
gatsby-node.js的createPages创建的模板页面不支持getServerData,该API仅对src/pages目录下的页面生效(包括文件系统路由页面)。 - 文件系统路由的变量传递问题,可通过规范路由命名、匹配变量类型解决,同时该方案天然支持
getServerData。
推荐解决方案:文件系统路由实现全需求
1. 创建动态路由页面
在src/pages目录下创建对应路由文件:
- 单层级slug:
[slug].js(如访问/shirt时,slug值为shirt) - 多级路径:
[...slug].js(如访问/men/shirt时,slug为数组["men", "shirt"])
2. 传递slug到页面查询
对于[slug].js,Gatsby会自动将路由参数作为查询变量$slug传入,直接使用你的查询即可:
export const query = graphql` query CollectionPageQuery($slug: String) { allCmsPlp( filter: { parameters: { collection: { seo: { slug: { eq: $slug } } } } } ) { edges { node { parameters { collection { seo { slug } brandId categoryId generic clusterId } } sections { name data } } } } } `
若使用[...slug].js,需将变量类型改为[String],并调整过滤逻辑(比如用in替代eq)。
3. 集成getServerData
直接在页面组件中导出getServerData函数,从context.params获取slug并执行SSR查询:
export async function getServerData(context) { const { slug } = context.params; // 示例:调用外部API获取SSR数据 const res = await fetch(`https://your-api.com/collection/${slug}`); const serverData = await res.json(); return { props: { serverData } }; } // 组件中同时使用页面查询数据和SSR数据 export default function CollectionPage({ data, serverData }) { const cmsData = data.allCmsPlp.edges[0]?.node; return ( <div> <h1>{cmsData?.parameters?.collection?.seo?.slug}</h1> <div>{JSON.stringify(serverData)}</div> </div> ); }
备选方案:createPages静态生成(无getServerData支持)
若必须用createPages创建页面,只能实现静态生成/增量再生,无法使用getServerData:
1. 在gatsby-node.js中传递context
exports.createPages = async ({ graphql, actions }) => { const { createPage } = actions; // 查询所有需要生成页面的slug const { data } = await graphql(` query { allCmsPlp { edges { node { parameters { collection { seo { slug } } } } } } } `); // 遍历生成页面 data.allCmsPlp.edges.forEach(edge => { const slug = edge.node.parameters.collection.seo.slug; createPage({ path: `/collections/${slug}`, component: require.resolve("./src/templates/collection.js"), context: { slug } // 将slug传入模板查询 }); }); };
2. 模板页面中接收变量
模板查询与之前一致,变量$slug会自动从context中获取。
问题排查指南
- 文件系统路由查询变量不存在:
- 确认页面文件在
src/pages目录下,命名格式正确(如[slug].js) - 访问路径需包含有效slug(如
/your-collection) - 检查变量类型与路由匹配(单层级用
String,多层级用[String])
- 确认页面文件在
- getServerData不生效:
- 仅
src/pages下的页面支持该API,模板页面(src/templates)不兼容 - 修改
getServerData后需重启Gatsby开发服务
- 仅
内容的提问来源于stack exchange,提问作者OrangeGio
相关产品推荐
相关产品推荐

