gatsbygraphql

Typer vos données avec Gatsby et Graphql

Comment typer proprement vos données en gatsby et graphql, afin d'éviter les erreurs de compilations pour les données manquantes.

Dans cet article, je vais vous parler un peu de mon expérience avec gatsby, et des limitations qui m’ont un peu surpris lorsque je commencer à jouer un peu plus avec le code.

Le typage des données

Vous avez monté votre blog, et pour chacun des posts vous utilisez MarkdownRemark. La structure de votre fichier .md ressemble à ceci :

---
draft: false
permalink: article-blog
tags:
  - Hello
authors:
  - SnowPact
title: Mon article de Blog
date: 2021-01-30T07:03:47.149Z
excerpt: Ma description SEO
image: ../assets/default.jpg
footer: Le mot de la fin
---

# Mon titre
## Mon contenu markdown...

Dans votre page template, vous avez sûrement une requête graphql de ce type

 query($slug: String, $primaryTag: String) {
    markdownRemark(fields: { slug: { eq: $slug } }) {
      html
      htmlAst
      excerpt
      timeToRead
      parent {
        ... on File {
          modifiedTime
        }
      }
      frontmatter {
        title
        date
        tags
        footer
        draft
        excerpt
        image {
          childImageSharp {
            fluid(maxWidth: 2000) {
              ...GatsbyImageSharpFluid
            }
          }
        }
        authors {
          id
        }
      }
    }

Lorsque vous avez quelques articles, vous éxecutez un gatsby build ou un gatsby develop, le projet compile bien et vous avez vos premiers post bien générés.

Maintenant modifiez la propriété footer de tous vos fichiers, et mettez les à vide. Et la qu’est-ce qu’il se passe quand vous essayez de recompiler ?

Erreur !

Comment gatsby vous mets à disposition les données de vos fichiers de sources ?

Le simple fait d’avoir une propriété à vide (null rééllement), peut faire planter votre compilation. Pourquoi ?

Ce qu’il se passe en fait lors du build, c’est que Gatsby va parcourir toute vos sources de données, et "inférer" les données. Il va vérifier dans chaque node ce que vous avez, et créer le typage graphql. C’est l’étape du (Schema Inference)[https://www.gatsbyjs.com/docs/schema-inference/].

Pour illustrer avec le cas précédent, si aucun fichier comporte un footer avec une donnée, Graphql ne mettra pas à disposition de propriété footer lors de vos query, et boom ça plantera.

En d’autres mots, si vous avez une données “nullable”, et qu’aucun des fichiers a une valeur pour cette donnée, alors adieu la compilation !

La solution : createSchemaCustomization

Mais tout n’est pas peine perdu. Gatsby met à votre disposition une page qui vous explique (comment régler ce soucis)[https://www.gatsbyjs.com/docs/reference/graphql-data-layer/schema-customization/].

Ça se passe dans le fichier gatsby-node.js, lors de l’étape createSchemaCustomization, et ça ressemble à ça :

exports.createSchemaCustomization = ({ actions }) => {
  const { createTypes } = actions
  const typeDefs = `
    type AuthorJson implements Node {
      joinedAt: Date
    }
  `
  createTypes(typeDefs)
}

Gatby met à votre disposition une méthode createTypes qui permet de typer votre objet. Si on applique cela à notre objet que nous avions précédemment :

exports.createSchemaCustomization = ({ actions }) => {
  const typeDefs = `
    type MarkdownRemark implements Node @infer {
      frontmatter: Frontmatter
      fileAbsolutePath: String
      fields: Fields
    }

    type Frontmatter {
      draft: Boolean!
      permalink: String!
      author: [AuthorYaml!]! @link
      tags: [String]
      title: String!
      date: Date
      excerpt: String!
      footer: String
      image: File! @fileByRelativePath
    }

    type Fields {
      slug: String!
    }
  `;

Ce qu’il se passe ici, c’est que vous indiquer à Gatsby le typage des données attendus. Vous devez commencer par l’objet qui héritera de Node (ici MarkdownRemark). Dedans se trouve notre frontmatter à qui on va créer un type Frontmatter, et spécifier les données.

Bref, j’imagine que vous avez déjà compris sans expliquer ce que ça fait. Je vais juste vous expliquer les différentes annotations / types présents :

Typage Graphql et Gatsby

NomTypeDescription
@inferAnnotation(optionnel) Indique à gatsby qu’il peut inférer également les données de ce type
@dontInferAnnotationIndique à gatsby que nous sommes sûr de ce type, et qu’on ne veut pas qu’il parcours les données. Cela fera economiser du temps de build pour les plus gros projets
@linkAnnotationPermet de linker avec une autre source de donnée, en le liant à la propriété id de l’autre côté
@fileByRelativePathAnnotationPermet de lier à une image locale lorsque vous avez un lien relatif. C’est ce que gatsby fait par défaut pour vos images
BooleanTypeValeur de type boolean
StringTypeValeur de type string
DateTypeValeur de type date
[XXX]TypeTableau de type XXX
!TypeA la fin d’un type, le ! permet d’indiquer que cette valeur ne peut pas être null

Bien entendu vous pouvez créer vos types comme on l’a vu plus haut.

@link vs mapping

On va revenir sur le @link. Vous avez sûrement dans votre projet des auteurs, un AuthorYml ou AuthorJson, que vous allez unir avec vos articles.

Et vous avez également peut-être dans votre fichier gatsby-config.js, cette propriété mapping proposée par gatsby pour rendre disponible automatiquement dans vos requètes qui vise le blog, l’auteur lié directement :

module.exports = {
  ...,
  mapping: {
     'MarkdownRemark.frontmatter.author': 'AuthorYaml',
  },
};

Exemple :

frontmatter {
  ...
  authors {
    id
    avatar
  }
}

Mon conseil, enlever cette partie et utiliser plutôt @link. Cela permet de faire la même chose, avec le bénéfice de pouvoir gérer les auteurs null.

Conclusion

Si vous aimez réellement gatsby, et que vous commencez à vous intéresser un peu plus, alors il est sûr à 100% que vous allez rencontrer ce problème.

Alors prenez bien le temps de lire cet article, et commencez à typer vos données dès maintenant !


S'inscrire au SnowPact

Toute les dernières actualités autour de Mon Resto' Halal dans votre boite email.