在 Gatsby、GraphQL 和 Sanity 中使用 _raw 和普通数据进行推理

Posted

技术标签:

【中文标题】在 Gatsby、GraphQL 和 Sanity 中使用 _raw 和普通数据进行推理【英文标题】:Reasoning with _raw and normal data in Gatsby, GraphQL and Sanity 【发布时间】:2020-06-22 17:17:06 【问题描述】:

我刚刚开始使用 Gatsby 和 Sanity 无头 CMS。

在大多数情况下,它非常简单;但是了解通过 GraphQL 查询数据的最佳实践仍然困扰着我。我目前的做法只是在 GraphQL 操场上疯狂地点击我的 CMS 结构并找到我想要的东西。这行得通,但这种方法缺乏统一性让我感到不安。

例如,如果我想要 CMS 中某处的英雄图片,我需要执行以下操作:

query SomePageQuery($id: String) 
  sanitySomePage(id:  eq: $id ) 
    id
    heroImage 
      asset 
        fluid(maxWidth: 1500) 
          ...GatsbySanityImageFluid
        
      
    
  

但是如果我想要一些PortableText 块,那么我需要查询相应的_raw 任何类型的字段。所以,如果我的类型是introText,盖茨比也会提供_rawIntroText。我只能从这个 _raw 版本的数据中获取完整的 PortableText。像这样:

query SomePageQuery($id: String) 
  sanitySomePage(id:  eq: $id ) 
    id
    _rawIntroText
  

似乎,对于某些数据,您可以使用[Type],而有时您可以使用_raw[Type]

关于为什么会出现这种情况的文档并不多。而且我不确定这是通过 Sanity 还是 Gatsby 强制执行的。

我想我的问题是,为什么 _raw[Anything] 存在于 Gatsby 和/或 Sanity 世界中,人们如何决定使用哪个(除了在 GraphQL 操场和运行时试错)?

【问题讨论】:

【参考方案1】:

这来自 Sanity 构建和维护的 gatsby-source-sanity 插件。希望来自 Sanity 的人可以提供更多上下文,但实际上 _raw[FieldName] 条目会返回该字段的原始 JSON 数据。无前缀字段(例如fieldName)可能不是您想要的——它只会包含有关数据的元数据位。

我倾向于提取_raw[FieldName] 数据,然后直接将其传递给@sanity/block-content-to-react 组件,如下所示:

import React from "react"
import  graphql  from "gatsby"
import SanityBlockContent from "@sanity/block-content-to-react"

export default ( data:  page  ) => (
  <SanityBlockContent
    blocks=page.textContent
    projectId=process.env.GATSBY_SANITY_PROJECT_ID
    dataset=process.env.GATSBY_SANITY_DATASET
  />
)

export const query = graphql`
  query SomePageQuery($id: String) 
    page: sanitySomePage(id:  eq: $id ) 
      textContent: _rawTextContent
    
  
`

请注意,我使用 GraphQL 别名继续在我的组件中将字段称为 textContent,而不是将组件耦合到此 GraphQL 架构的细节。

您无需使用 Gatsby Image for Sanity 图像,因为它们有自己的图像转换管道。相反,您可以只获取asset _id ,然后像这样使用@sanity/client 来生成图片网址:

import sanityClient from "@sanity/client"
import sanityImageUrl from "@sanity/image-url"

const client = sanityClient(
  dataset: process.env.GATSBY_SANITY_DATASET,
  projectId: process.env.GATSBY_SANITY_PROJECT_ID,
  useCdn: true,
)

const builder = sanityImageUrl(client)

builder.image( _id: "..." ).width(400).dpr(2).url()

【讨论】:

谢谢。是的,这就是我目前处理块内容的方式。所以我听到的是,任何与理智相关的东西都被加载到_raw 前缀字段中,而盖茨比特有的任何东西都在其他字段中。例如,我正在使用gatsby-image,当我尝试输入_raw 字段时,它似乎不起作用。所以听起来我注定要根据具体情况考虑从哪里最好地获取这些数据?别名的技巧绝对有用,因为它可以帮助我在组件使用数据的方式上保持一定的一致性。 不同之处在于 _raw 字段在 GraphQL 模式中被键入为 JSON,并且像 Gatsby Image 这样的转换器不会在该节点类型上运行。有了 Sanity,你真的不需要在 GraphQL 查询中使用 Gatsby Image。您可以直接使用@sanity/client 包。我会更新一个例子。 感谢 @sanity/image-url 示例,但我之前也这样做过,但我们决定使用 Netlify CDN 来交付图像以提高速度。 Gatsby Image 似乎还具有更多功能。在主机服务器上使用 Sanity 实现的任何其他原因?显然,留在一个生态系统中的便利性将是一个加分项。 嗯,作为构建的一部分,您仍然需要实际下载所有图像。 Sanity 的资产 API 在前面使用了 Google Cloud CDN,所以我不知道使用 Netlify 会不会有很大的改进,尤其是考虑到每次部署时缓存失效的情况。 需要明确的是,你仍然可以使用带有 Sanity image-url 的 Gatsby Image React 组件,你只需构建自己的 srcSet 并将其交给。我个人不这样做,因为fluidfixed 方法不太灵活,但是 ymmv。 FWIW,您的 GraphQL 节点中的 SanityAsset 包含一个低分辨率预览,您可以嵌入(base64)而不是让 Gatsby 重新生成它。

以上是关于在 Gatsby、GraphQL 和 Sanity 中使用 _raw 和普通数据进行推理的主要内容,如果未能解决你的问题,请参考以下文章

如何通过 gatsby-source-sanity 在 sanity.io 和 gatsby 中使用内部链接?

我可以将 graphql API 数组合并/组合成一个吗?

运行 graphql deploy 时出现 Sanity groupProblems.js 错误

如何为 Gatsby 页面查询创建自定义解析器?

Gatsby:graphql 查询中的 gatsby-source-graphql 和 gatsby-plugin-sharp

看起来 apollo 客户端不会查询 id 具有 . (点)使用 Next JS 和 Sanity CMS with GraphQL