如何在Node与Gatsby页面间共享GraphQL片段?
嘿,这个问题我之前也碰到过,刚好能给你一套靠谱的解决方案,既能在Gatsby页面和Node API之间共享GraphQL片段,还能让两边的IDE都提供语法高亮支持~
步骤1:创建可复用的GraphQL片段
首先得把要共享的片段抽出来单独存放,推荐在src目录下建一个fragments文件夹,结构清晰好维护。
有两种方式定义片段:
方式A:用JS文件配合graphql模板标签
创建src/fragments/postFragments.js:
import { graphql } from "gatsby" // 定义片段,注意必须指定`on [数据类型]`,Gatsby才能识别它属于哪个数据源 export const postCardFragment = graphql` fragment PostCard on MarkdownRemark { id frontmatter { title date(formatString: "MMMM DD, YYYY") } excerpt(pruneLength: 150) } `
方式B:用单独的.graphql文件
创建src/fragments/postFragments.graphql:
fragment PostCard on MarkdownRemark { id frontmatter { title date(formatString: "MMMM DD, YYYY") } excerpt(pruneLength: 150) }
这种方式更纯粹,Gatsby会自动扫描项目中的.graphql文件并加载片段,不需要手动导入,省心不少。
步骤2:在页面组件中使用片段
不管你用哪种方式定义片段,页面里用起来都很简单:
import { graphql } from "gatsby" // 如果是JS文件定义的片段,需要导入(.graphql方式则不需要这一步) import { postCardFragment } from "../fragments/postFragments" export const pageQuery = graphql` query BlogIndex { allMarkdownRemark(sort: {frontmatter: {date: DESC}}) { nodes { # 直接引用共享片段 ...PostCard } } } `
这里IDE会正常识别graphql模板里的语法,提供高亮和提示,完全没问题。
步骤3:在Node API(gatsby-node.js)中使用片段并启用语法高亮
这是最容易踩坑的地方——createPages里的graphql是Gatsby注入的执行函数,不是模板标签。要解决语法高亮和片段共享问题,按下面的方法来:
方法一:配合导入的graphql模板标签
// 从gatsby导入graphql模板标签,重命名为gql避免和注入的执行函数冲突 import { graphql as gql } from "gatsby" // 如果是JS文件定义的片段,导入文件即可(不需要使用导出的变量,只要让Gatsby加载到片段就行) import "./src/fragments/postFragments" export async function createPages({ graphql, actions }) { const { createPage } = actions // 用导入的gql模板标签写查询,IDE会识别GraphQL语法并高亮 const queryResult = await graphql(gql` query GetAllPosts { allMarkdownRemark { nodes { # 直接引用共享片段 ...PostCard fields { slug } } } } `) // 处理查询结果并创建页面的逻辑 if (queryResult.errors) throw queryResult.errors queryResult.data.allMarkdownRemark.nodes.forEach(post => { createPage({ path: `/blog/${post.fields.slug}`, component: require.resolve("./src/templates/blog-post.js"), context: { slug: post.fields.slug }, }) }) }
方法二:用.graphql片段文件(更省心)
如果你的片段是放在.graphql文件里的,连导入都省了,直接写查询就行:
import { graphql as gql } from "gatsby" export async function createPages({ graphql, actions }) { const { createPage } = actions const queryResult = await graphql(gql` query GetAllPosts { allMarkdownRemark { nodes { ...PostCard # Gatsby自动加载了这个片段 fields { slug } } } } `) // ...创建页面逻辑 }
这里的核心逻辑是:导入的gql模板标签负责让IDE识别语法,而注入的graphql函数负责执行查询,两者各司其职,完美解决Node端的语法高亮问题。
常见问题排查
- 报错“Unknown fragment”:检查片段是否定义了
on [数据类型],或者片段文件是否在Gatsby的扫描范围内(默认src目录下的文件都会被扫描)。 - IDE不高亮Node端的查询:确保你用了从
gatsby导入的graphql/gql模板标签包裹查询字符串,而不是直接用普通的模板字符串。 - 片段字段不生效:确认片段里的字段和你查询的数据源类型匹配,比如
MarkdownRemark类型的片段不能用在Site类型的查询上。
内容的提问来源于stack exchange,提问作者Sebastien Lorber
相关产品推荐
相关产品推荐

