Il problema
Durante lo sviluppo di questo sito e di un altro progetto lavorativo che usava Gatsby, mi sono imbattuto in un problema: le mie query graphql fallivano apparentemente senza motivo. Su questo sito, uso dei file di markdown per creare i post, inserendo alcune informazioni nell’intestazione. Però, quando richiedevo alcuni dei campi inseriti nell’intestazione veniva generato un errore, che indicava che quei campi non esistevano.
Questo succede perché Gatsby richiede che tutti i campi siano compilati, almeno una volta. Su questo sito, ho quindi risolto creando un post fittizio e popolando tutti i campi. Purtroppo questa soluzione non si poteva applicare in modo semplice al mio progetto di lavoro.
Vediamo quindi un metodo migliore per risolvere il problema.
L’API ‘Schema Customization’
Da circa un anno è disponibile un insieme di funzioni che ci permettono di modificare gli schemi graphql generati da Gatsby.
Vediamo come usare l’API createSchemaCustomization
e l’action createTypes
.
Porterò come esempio la situazione che mi era capitata a lavoro. In quel progetto ho utilizzato Strapi come CMS e l’ho collegato
a Gatsby con il plugin gatsby-source-strapi
. Avevo creato un contenuto chiamato “Product” con dei campi opzionali “website” e “pdf”,
che però mi causavano il suddetto errore, dato che non li avevo mai compilati.
Per iniziare, dobbiamo implementare l’API createSchemaCustomization
nel file gatsby-node.js
:
exports.createSchemaCustomization = ({ actions }) => {
// ...
};
Ora possiamo estrarre l’azione chiamata createTypes
e passargli una stringa che utilizza il Linguaggio degli Schemi di Graphql:
exports.createSchemaCustomization = ({ actions }) => {
let { createTypes } = actions;
const types = `
type StrapiProduct implements Node @infer {
website: String
pdf: File
}
`;
createTypes(types);
};
Vediamo cosa significa il codice per la creazione del Tipo:
type StrapiProduct
indica il nome del Tipo da estendereimplements Node
serve perché Gatsby utilizza questa interfaccia per la maggioranza dei dati generati dai plugin (nel mio caso, il plugin gatsby-source-strapi)@infer
specifica che questa dichiarazione di Tipo non contiene tutti i dati, ma che è un’estensione di un Tipo già presente.
Poi, ho inserito all’interno i vari campi in modo abbastanza semplice, usando questo metodo: nomeCampo: TipoCampo
. Potete trovare un insieme dei
tipi di dati disponibili in Graphql nella documentazione sul Linguaggio degli Schemi di Graphql (citata sopra).
In alcuni casi, questo potrebbe già essere sufficiente. Però, quando ho scritto quel codice sono stato abbastanza ingenuo, e alla fine non riuscivo a recuperare i dati del pdf. Questo perché il tipo era sbagliato o, per essere precisi, incompleto.
Come facciamo a trovare il tipo di dato corretto per completare il nostro codice? Qui mi è venuta in aiuto una domanda trovata su StackOverflow (link in fondo alla pagina) che mi ha mostrato una tecnica semplice ed efficace.
Come identificare il tipo di un campo
Prima di tutto dobbiamo creare dei dati fittizi, in modo che Gatsby possa generare il suo schema senza bisogno delle nostre indicazioni.
A questo punto, possiamo chiedere a Gatsby di salvare tutti i tipi di dati che ha generato dentro ad un file di testo. Per farlo
c’è un’azione che possiamo sfruttare dentro a createSchemaCustomization
:
exports.createSchemaCustomization = ({ actions }) => {
// Commentiamo il codice, così da lasciare a Gatsby il compito di generare i Tipi
// let { createTypes } = actions;
// const types = `
// type StrapiProduct implements Node @infer {
// website: String
// pdf: File
// }
// `;
// createTypes(types);
actions.printTypeDefinitions({ path: "./types.txt" });
};
Dopo aver eseguito il comando gatsby develop
, vedremo che verrà generato il file ‘types.txt’ nella cartella base del progetto.
Andiamo quindi a vedere cosa contiene. Nel mio caso, ho scoperto che per il Tipo “StrapiProduct”, il campo pdf aveva questo
aspetto:
type StrapiProducts implements Node ... {
...
pdf: File @link(by: "id", from: "pdf___NODE")
...
}
A questo punto possiamo copiare il Tipo corretto (quello generato da Gatsby) e incollarlo nel nostro codice:
exports.createSchemaCustomization = ({ actions }) => {
let { createTypes } = actions;
const types = `
type StrapiProduct implements Node @infer {
website: String
pdf: File @link(by: "id", from: "pdf___NODE")
}
`;
createTypes(types);
};
Ora non resta altro che accertarci che le query funzionino ed eliminare i dati fittizi.
Spero che queste informazioni siano state utili a voi tanto quanto lo sono state a me 🙂️
Riferimenti
Questi sono i riferimenti che ho guardato e che mi sono stati utili per risolvere il problema:
- Documentazione di Gatsby
- Documentazione sull’action
createTypes
- Articolo sul blog di Gatsby
- Gatsby-source-strapi, issue #86
- StackOverflow, domanda #64065878