web-dev-qa-db-ja.com

GatsbyにGraphQLスキーマを与える方法

Wordpressバックエンドからいくつかの投稿を取り込みます。一部は(ACFフィールドに)写真があり、一部はありません。問題は、Gatsbyが最初のノードに基づいてスキーマを推測することです。画像のないノードを受信した場合、スキーマは間違っています。

GatsbyのGraphQLスキーマはどこから来るのですか? 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',
  ],
}
14
Ashbury

この投稿からしばらく経ちましたが、バージョン2.2以降 Gatsbyは新しいAPIを追加しました これにより、スキーマのカスタマイズがはるかに簡単になります。これはwordpressの例ではありませんが、gatsbyのgatsby-transformer-remarkの例ですが、適用できると確信しています。

.mdがたくさんあり、frontmatterは次のようになっています。

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

...content...

ギャツビーが最初に空の画像で.mdに到達すると、そのフィールドはStringであるはずですが、誤ってFileと推測されます。新しいAPIを使用すると、gatsby-node.jsの画像フィールドについてGatsbyに伝えることができます。

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

    type MarkdownRemark implements Node {
      frontmatter: MarkdownRemarkFrontmatter
    }
  `)
}

これにより、imageフィールドが常にファイルタイプであることが保証されます。それ以外の場合は、nullになります。

いくつかのメモ:

  • MarkdownRemarkのようなルートノードはNodeを実装する必要があります
  • ノードは複数のインターフェースを実装できます
  • あなたは、関連する分野まで「あなたのやり方で働く」必要があります。この例では、MarkdownRemarkFrontmatterタイプを宣言してから、それをfrontmatterノードのMarkdownRemarkフィールドに渡す必要があります。
  • 指定しない場合、ギャツビーは残りのフィールドを推測します。上記の例では、categoryMarkdownRemarkFrontmatterフィールドを指定しなかったため、以前と同じようにギャツビーによって推測されます。
  • これらのタイプ(MarkdownRemarkMarkdownRemarkFrontmatter)を見つける最も役立つ方法は、graphiqlでそれらを探すことです(localhost:8000/___graphqlのデフォルト)。
12
Derek Nguyen

まず、Gatsby-plugin-sharp、Gatsby-transform-sharp、およびGatsby-source-WordPressプラグインを使用していますか?

私のサイトでは、Gatsby-source-WordpressプラグインとSharpライブラリのほか、Promiseを返すためのBluebirdを使用しています。Post.jsまたはPage.jsでImageURLを定義します。ソースURLは、メディアライブラリに読み込まれたときに生成されますが、my 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はスキームを正しく返さず、エラーが発生します。簡単に聞こえ、重複しているため、同時に2つの異なるGraphQLスキーマと、異なる投稿カテゴリを定義する2つの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
                }
            }
        }
    }

`

これが私にメッセージを送るのを遠慮なく助けてくれることを願っています。

0
Nick C

そのためのプラグインがあり、それは素晴らしいです。具体的には、Wordpressソースプラグインで使用しています。

IDEを正しく取得するには、graphql.config.jsonファイルをルートディレクトリに追加する必要がある場合があります。

{
  "schema": {
    "file": "schema.json"
  }
}
0
Bryce York