web-dev-qa-db-fra.com

Comment donner à Gatsby un schéma GraphQL

Nous introduisons des articles depuis un backend Wordpress, certains ont des images (dans un champ ACF) et d'autres pas. Le problème est que Gatsby infère le schéma basé sur le premier nœud s'il reçoit un nœud sans image, le schéma est incorrect.

D'où vient le schéma GraphQL de Gatsby? Avec Gatsby, nous utilisons des plugins qui récupèrent les données de différentes sources. Nous utilisons ensuite ces données pour déduire automatiquement un schéma GraphQL.

Comment pouvons-nous dicter un schéma à GraphQL/Gatsby qui inclut toujours une image, avec 'null' comme valeur par défaut si elle est vide?

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

Dans l'exemple ci-dessus, parfois 'photo' n'existe pas et ça casse tout ...

Configuration Gatsby:

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

Cela fait un moment depuis ce post, mais depuis la version 2.2 Gatsby a ajouté une nouvelle API qui facilitera la personnalisation du schéma. Ce n'est pas un exemple avec wordpress mais avec gatsby's gatsby-transformer-remark, mais je suis sûr que c'est applicable.

J'ai un tas de .md avec frontmatter ressemble à ceci:

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

...content...

Si Gatsby arrive au .md avec l'image vide en premier, il déduira incorrectement ce champ comme String, même s'il doit être File. Avec la nouvelle API, je peux informer Gatsby du champ d'image dans gatsby-node.js:

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

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

Cela garantira que le champ image sera toujours de type File, sinon ce sera null.

Quelques notes:

  • Les nœuds racine comme MarkdownRemark doivent implémenter Node
  • Un nœud peut implémenter plusieurs interfaces
  • Vous devez "vous frayer un chemin" vers le champ correspondant. Dans cet exemple, je dois déclarer le type MarkdownRemarkFrontmatter, puis le transmettre au champ frontmatter dans le nœud MarkdownRemark.
  • Gatsby déduira le reste des champs s'il n'est pas spécifié. Dans l'exemple ci-dessus, puisque je n'ai pas spécifié le champ category dans MarkdownRemarkFrontmatter, il sera déduit par Gatsby comme avant.
  • Le moyen le plus utile pour trouver ces types (MarkdownRemark, MarkdownRemarkFrontmatter) est de les rechercher dans graphiql (par défaut à localhost:8000/___graphql)
12
Derek Nguyen

Commencez-vous par utiliser les plug-ins Gatsby-plugin-sharp, Gatsby-transform-sharp & Gatsby-source-WordPress?

Mon site utilise le plugin Gatsby-source-Wordpress ainsi que la bibliothèque pointue ainsi que Bluebird pour renvoyer des promesses, etc. Définissez l'ImageURL sur votre Post.js ou Page.js. L'URL source est produite lorsqu'elle est chargée dans ma bibliothèque multimédia mais est déchargée dans un compartiment S3 car mon site WordPress est construit "par programme". L'URL source est généralement définie par vous et peut être choisie dans Types de champs ACF lors de la création d'un modèle de publication de page.

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
          }
        }
      }
    }
  } 

L'interrogation des données dans l'ordre exact est un must pour chaque type de publication ou GraphQL ne renverra pas le schéma correctement, ce qui produira une erreur. Aussi simple que cela puisse paraître et faisant double emploi, il devra y avoir deux schémas GraphQL différents à la fois et deux fichiers post1.js exemple post1.js et post2.js définissant les différentes catégories de messages. 1. Recherchez le retour avec l'URL des images. 2. Requête pour le retour sans images. égal à nul ou inexistant C'est une chute de GraphQL qu'il s'attend à recevoir X et quand Y arrive, il devient mécontent et échoue.

Vous pouvez également essayer ceci lorsque vous recevez l'image, la transformer avec sharp en href = et la transformer de https pour la dimensionner à la réception, mais dans votre schéma de cas, elle sera nulle. Nous l'avons fait pour une page bio d'un employé qui revenait d'un ancien site 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
                }
            }
        }
    }

"

J'espère que cela vous aide à me contacter.

0
Nick C

Il y a un plugin pour ça, et c'est génial. Je l'utilise spécifiquement avec le plugin source Wordpress.

Notez que vous devrez peut-être également ajouter un graphql.config.json fichier dans votre répertoire racine pour votre IDE pour le récupérer correctement:

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