Skip to main content

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

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 :

# content/blog/article-blog.md

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

"""
src/templates/post.tsx
"""

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éellement), 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.

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.

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

// gatsby-node.js

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

 

Gatsby 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 :

// gatsby-node.js

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@ `infer` Annotation(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 `@link` Annotation permet de linker avec une autre source de donnée, en le liant à la propriété `@id`de l’autre côté `@fileByRelativePath` Annotation permet de lier à une image locale lorsque vous avez un lien relatif. C’est ce que gatsby fait par défaut pour vos images `Boolean` TypeValeur de type boolean `String` TypeValeur de type string `Date` TypeValeur 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 !