【问题标题】:How to give Gatsby a GraphQL schema如何给 Gatsby 一个 GraphQL 模式
【发布时间】:2023-04-08 10:58:01
【问题描述】:

我们从 Wordpress 后端引入了一些帖子,有些有图片(在 ACF 字段中),有些没有。问题是 Gatsby 根据它接收到的第一个节点推断模式。如果它接收到一个没有图片的节点,那么架构是错误的。

Where does Gatsby’s GraphQL schema come from? 在 Gatsby 中,我们使用从不同来源获取数据的插件。然后,我们使用该数据自动推断 GraphQL 架构。

我们如何为 GraphQL/Gatsby 指定一个始终包含图片的架构,如果它是空白的,则将“null”作为默认值?

{
  allWordpressWpTestimonial {
    edges {
      node {
        id
        title
        acf {
          photo_fields {
            photo {
              id
              localFile {
                childImageSharp {
                  sizes {
                    src
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

在上面的示例中,有时“照片”不存在,它破坏了一切......

盖茨比配置:

const innertext = require('innertext')
const url = require('url')

module.exports = {
  siteMetadata: {
    title: 'Test',
    googleMapsAPIKey: 'xxxxxx',
    adminBaseUrl: '123.123.123',
    adminProtocol: 'http',
  },
  pathPrefix: '/web/beta',
  plugins: [
    'gatsby-plugin-react-next',
    'gatsby-plugin-react-helmet',
    'gatsby-plugin-sharp',
    'gatsby-plugin-svgr',
    {
      resolve: 'gatsby-plugin-google-analytics',
      options: {
        trackingId: 'GOOGLE_ANALYTICS_TRACKING_ID',
      },
    },
    {
      resolve: 'gatsby-plugin-bugherd',
      options: {
        key: 'xxxxxx',
        showInProduction: true,
      },
    },
    {
      resolve: '@andrew-codes/gatsby-plugin-elasticlunr-search',
      options: {
        fields: ['title', 'url', 'textContent', 'urlSearchable'],
        resolvers: {
          wordpress__PAGE: {
            title: node => node.title,
            textContent: node => innertext(node.content),
            url: node => url.parse(node.link).path,
            urlSearchable: node =>
              url
                .parse(node.link)
                .path.split('/')
                .join(' '),
          },
          wordpress__POST: {
            title: node => node.title,
            textContent: node => innertext(node.content),
            url: node => `/news/${node.slug}`,
            urlSearchable: node =>
              url
                .parse(node.link)
                .path.split('/')
                .join(' '),
          },
          wordpress__wp_industry: {
            title: node => node.title,
            textContent: node => innertext(node.content),
            url: node => `/business/industries/${node.slug}`,
            urlSearchable: node =>
              url
                .parse(node.link)
                .path.split('/')
                .join(' '),
          },
        },
      },
    },
    {
      resolve: 'gatsby-source-wordpress',
      options: {
        baseUrl: 'xxxxxx',
        protocol: 'http',
        hostingWPCOM: false,
        useACF: true,
        auth: {
          htaccess_user: 'admin',
          htaccess_pass: 'xxxxxx',
          htaccess_sendImmediately: false,
        },
        verboseOutput: false,
      },
    },
    'gatsby-transformer-sharp',
  ],
}

【问题讨论】:

  • 您使用哪个插件从 Wordpress 中提取源代码?你能分享你的 gatsby 配置文件吗?
  • gatsby-source-wordpress,将使用 gatsby 配置进行更新

标签: javascript reactjs graphql gatsby


【解决方案1】:

首先,您使用的是 Gatsby-plugin-sharp、Gatsby-transform-sharp 和 Gatsby-source-WordPress 插件吗?

我的网站使用 Gatsby-source-Wordpress 插件加上 sharp 库以及 Bluebird 来返回承诺等。 在 Post.js 或 Page.js 上定义 ImageURL。源 URL 是在我的媒体库中加载时生成的,但由于我的 WordPress 网站是“以编程方式”构建的,因此会被卸载到 S3 存储桶中。 源 URL 通常由您定义,并且可以在构建页面模板的帖子时在 ACF 字段类型中选择。

export const pageQuery = graphql`
  query homePageQuery {
    site {
      siteMetadata {
        title
        subtitle
        description
      }
    }

    allWordpressPost(sort: { fields: [date] }) {
      edges {
        node {
          title
          excerpt
          slug
          type
          _image{
            source_url
          }
          categories {
            slug
            name
          }
        }
      }
    }
  } 

对于每种帖子类型都必须按确切顺序查询数据,否则 GraphQL 将无法正确返回方案,从而产生错误。 听起来很简单且重复,有时必须有两种不同的 GraphQL 方案和定义不同帖子类别的两个 post.js 示例 post1.js 和 post2.js 文件。 1.用图片URL查询返回。 2.查询没有图片的退货。等于 null 或不存在 这是 GraphQL 的失败,它期望接收 X,而当 Y 发生时,它会不高兴并失败。

当您收到图像时,您也可以尝试此操作,将其转换为 href= 并将其从 https 转换为接收时的大小。但在您的情况下,将其设置为 null。 我们为从旧 WordPress 网站返回的员工简历页面执行此操作。

/**
     * Transform internal absolute link to relative.
     * 
     * @param {string} string The HTML to run link replacemnt on
     */
    linkReplace(string) {
        // console.log(string)
        const formatted = string.replace(
            /(href="https?:\/\/dev-your-image-api\.pantheonsite\.io\/)/g,
            `href="/`
        )

        return formatted
    }

    render() {
        const post = { ...this.props.data.wordpressPost }
        const headshot = { ...this.props.data.file.childImageSharp.resolutions }
        const { percentScrolled } = { ...this.state }
        const contentFormatted = this.linkReplace(post.content)

        return (
            <div ref={el => (this.post = el)}>
                <div className={styles.progressBarWrapper}>
                    <div
                        style={{ width: `${percentScrolled}%` }}
                        className={styles.progressBar}
                    />
                </div>

                <div className={styles.post}>
                    <h1
                        className={styles.title}
                        dangerouslySetInnerHTML={{ __html: post.title }}
                    />

                    <div
                        className={styles.content}
                        dangerouslySetInnerHTML={{ __html: contentFormatted }}
                    />

                    <Bio headshot={headshot} horizontal={true} />
                </div>
            </div>
        )
    }
}

Post.propTypes = {
    data: PropTypes.object.isRequired,
}

export default Post

export const postQuery = graphql`
    query currentPostQuery($id: String!) {
        wordpressPost(id: { eq: $id }) {
            wordpress_id
            title
            content
            slug
        }
        file(relativePath: { eq: "your-image-headshot.jpg" }) {
            childImageSharp {
                resolutions(width: 300, height: 300) {
                    ...GatsbyImageSharpResolutions
                }
            }
        }
    }

`

希望这有助于随时给我发消息。

【讨论】:

    【解决方案2】:

    这篇文章已经有一段时间了,但是从版本 2.2 Gatsby has added a new API 开始,这将使自定义架构变得更加容易。这不是 wordpress 的示例,而是 gatsby 的 gatsby-transformer-remark,但我确信它是适用的。

    我有一堆.md 的frontmatter 看起来像这样:

    ---
    title: "Screen title"
    image: "./hero-image.png"  <--- sometimes it's an empty string, ""
    category: "Cat"
    ---
    
    ...content...
    

    如果 Gatsby 首先使用空图像访问.md,它会错误地将该字段推断为String,即使它应该是File。使用新的 API,我可以告诉 Gatsby gatsby-node.js 中的图像字段:

    exports.sourceNodes = ({ actions, schema }) => {
      const { createTypes } = actions
      createTypes(`
        type MarkdownRemarkFrontmatter {
          image: File
        }
    
        type MarkdownRemark implements Node {
          frontmatter: MarkdownRemarkFrontmatter
        }
      `)
    }
    

    这将保证image 字段始终为文件类型,否则将为null

    一些注意事项:

    • MarkdownRemark这样的根节点必须实现Node
    • 一个节点可以实现多个接口
    • 您必须“按自己的方式”进入相关领域。在此示例中,我必须声明 MarkdownRemarkFrontmatter 类型,然后将其传递给 MarkdownRemark 节点中的 frontmatter 字段。
    • 如果未指定,Gatsby 将推断其余字段。在上面的例子中,由于我没有在MarkdownRemarkFrontmatter 中指定category 字段,它会像之前一样被盖茨比推断出来。
    • 查找这些类型(MarkdownRemarkMarkdownRemarkFrontmatter)最有用的方法是在 graphiql 中查找它们(默认为 localhost:8000/___graphql

    【讨论】:

    • 我正在努力让它与 wordpress 和 acf 一起使用。每个节点都有一个 ACF 对象,其中包含一个转发器对象,其中包含一个包含 3 个字符串(标题、url、目标)的链接的数组。我已经尝试创建上述一系列函数来一直挖掘到 3 个字符串,这对我不起作用。 { allWordpressPost { 边 { 节点 { title acf { project_students 合作伙伴 { partner_link { title url target } } } } } }
    猜你喜欢
    • 2018-10-26
    • 2021-08-18
    • 2020-08-28
    • 2019-02-19
    • 2018-06-16
    • 1970-01-01
    • 2018-04-06
    • 2021-05-04
    • 2019-01-23
    相关资源
    最近更新 更多