Gatsby

,

GraphQL

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.

Murat

Murat

25 février 2021

Typer vos données avec Gatsby et Graphql

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 :

# 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@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 imagesBooleanTypeValeur de type booleanStringTypeValeur de type stringDateTypeValeur 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 !

Technologies dans cet article ...

Front-End

Gatsby

Gatsby