如何在Prismic的Content与Theme自定义类型间复用GraphQL Fragment?
Prismic 同结构自定义类型的GraphQL Fragment复用方案
完全可以实现复用,不需要在两套查询逻辑里重复编写一遍Slice字段。
因为Prismic的Gatsby源插件特性,哪怕两个自定义类型(Content/Theme)下配置的Slice结构完全一致,插件也会为每个自定义类型独立生成GraphQL类型——比如PrismicContentBodyCollection和PrismicThemeBodyCollection是两个完全独立的类型,没有公共继承关系,所以你现在硬绑定在PrismicContentBodyCollection上的Fragment没法直接在Theme类型的查询里用,但可以通过下面两种方式实现零重复复用:
方案一:自定义公共GraphQL接口(最彻底的复用方式)
只需要通过Gatsby的Schema定制能力,给两个同结构的Slice类型绑定同一个公共接口,之后Fragment直接绑定到公共接口上,就能同时被两个类型复用,完全不需要重复写字段逻辑。
- 在项目根目录的
gatsby-node.js里添加Schema自定义逻辑:
exports.createSchemaCustomization = ({ actions }) => { const { createTypes } = actions // 不需要重写原有类型的所有字段,只需要声明公共接口和类型实现关系即可 createTypes(` # 定义公共接口,按需列出两个Slice共有的字段 interface CollectionSlice { slice_type: String! primary: CollectionSlicePrimary items: [CollectionSliceItem] } # 声明插件自动生成的两个类型实现这个公共接口 type PrismicContentBodyCollection implements CollectionSlice type PrismicThemeBodyCollection implements CollectionSlice `) }
- 把原来的Fragment直接绑定到公共接口上,一次编写就能同时在两个类型下生效:
export const CollectionFragment = graphql` fragment CollectionFragment on CollectionSlice { slice_type primary { # 所有原来的字段查询逻辑都正常写在这里即可 } items { # 嵌套字段也正常复用 } } `
方案二:无Schema改动的轻量复用
如果不想调整自定义Schema,也可以通过模板字符串抽离公共字段逻辑,避免重复编写嵌套查询:
- 把所有需要复用的Slice字段查询逻辑抽成独立的字符串常量:
// 所有公共字段查询逻辑只写一次 const commonCollectionFields = ` slice_type label primary { heading description } items { name cover } `
- 分别在两个对应的Slice类型上声明同名结构的Fragment,直接引用上面的常量即可:
export const CollectionFragment = graphql` fragment CollectionContentFragment on PrismicContentBodyCollection { ${commonCollectionFields} } fragment CollectionThemeFragment on PrismicThemeBodyCollection { ${commonCollectionFields} } `
- 在实际查询的时候,根据当前查询的类型引入对应的Fragment即可:
query MyQuery { allPrismicTheme { nodes { data { body { ... on PrismicThemeBodyCollection { ...CollectionThemeFragment } } } } } allPrismicContent { nodes { data { body { ... on PrismicContentBodyCollection { ...CollectionContentFragment } } } } } }
注意:不要直接把现有绑定
PrismicContentBody*类型的Fragment强行应用到Theme类型的查询上,GraphQL会直接抛出类型不匹配的运行错误——这两个类型是插件独立生成的,不存在跨类型的片段引用能力。
内容的提问来源于stack exchange,提问作者fuzz
相关产品推荐
相关产品推荐

