Utilizzo avanzato di GraphQL nei siti Web di Gatsby

Pubblicato: 2022-03-10
Riepilogo rapido ↬ In questo articolo, Aleem Isiaka spiega cosa sono i costrutti di query GraphQL e come possono essere utilizzati per interagire con il livello di accesso ai dati di un sito Web Gatsby. Diamo un'occhiata ad alcuni dei casi d'uso avanzati di GraphQL all'interno di un sito Web Gatsby utilizzando dati di corrispondenza provenienti da fonti diverse.

Prima del rilascio di GraphQL nel 2015, Representational State Transfer (REST) ​​era il modo principale per interfacciarsi con un'API. L'introduzione di GraphQL è stato quindi un importante cambiamento nello sviluppo del software.

In qualità di moderno generatore di siti statici, Gatsby sfrutta GraphQL per fornire una metodologia concisa per l'inserimento e la manipolazione dei dati nel framework. In questo articolo, daremo un'occhiata più da vicino a GraphQL e come possiamo integrarlo in un sito Web di Gatsby costruendo e implementando l'approvvigionamento e la trasformazione dei dati avanzati in Gatsby. Il risultato è un blog di un editore che potrebbe essere utilizzato da qualsiasi casa editrice per condividere i contenuti dei propri autori.

Che cos'è GraphQL?

Prendendo il nome da QL , GraphQL è un linguaggio di query combinato con un insieme di strumenti creati per fornire flessibilità ed efficienza nel modo in cui estraiamo i dati da una fonte. Con GraphQL, un cliente/consumatore può richiedere esattamente i dati di cui ha bisogno. Il server/provider risponde con una firma di risposta JSON che soddisfa i requisiti specificati nella query. Ci consente di esprimere le nostre esigenze di dati in modo dichiarativo.

Perché usare GraphQL?

In quanto generatore di siti statici, Gatsby archivia file statici, il che rende quasi impossibile eseguire query sui dati. Spesso ci sono componenti della pagina che devono essere dinamici come la singola pagina del post del blog, quindi sorgerebbe la necessità di estrarre i dati da una fonte e trasformarli nel formato necessario, proprio come avere i post del blog archiviati in file markdown. Alcuni plugin forniscono dati da varie fonti, il che ti lascia con l'interrogazione e la trasformazione dei dati richiesti da una fonte.

Secondo un elenco su gatsby.org, GraphQL è utile in Gatsby per:

  • Elimina il boilerplate
  • Spingi le complessità del frontend nelle query
  • Fornisci una soluzione perfetta per i dati sempre complessi di un'applicazione moderna
  • Infine, per rimuovere il rigonfiamento del codice, migliorando così le prestazioni.

Concetti di GraphQL

Gatsby mantiene le stesse idee di GraphQL ampiamente utilizzate; alcuni di questi concetti sono:

Linguaggio di definizione degli schemi

GraphQL SDL è un sistema di tipi incorporato in GraphQL e puoi usarlo per creare nuovi tipi per i tuoi dati.

Possiamo dichiarare un tipo per un paese e i suoi attributi potrebbero includere un nome, un continente, una popolazione, un PIL e un numero di stati.

Come esempio di seguito, abbiamo creato un nuovo tipo con il nome di Aleem . Ha hobbies che sono una serie di stringhe e non sono richiesti, ma sono necessari paese, stato civile e post a causa del ! includono, anche post, riferimenti di un altro tipo, Post .

 type Author { name: String!, hobbies: [String] country: String! married: Boolean! posts: [Post!] } type Post { title: String! body: String! } type Query { author: Author } schema { query: Query }

Interrogazioni

Possiamo usare Query per estrarre dati da una sorgente GraphQL.

Considerando un set di dati come il seguente

 { data: { author: [ { hobbies: ["travelling", "reading"], married: false, country: "Nigeria", name: "Aleem Isiaka", posts: [ { title: "Learn more about how to improve your Gatsby website", }, { title: "The ultimate guide to GatsbyJS", }, { title: "How to start a blog with only GatsbyJS", }, ], }, ], }, };

Possiamo avere una query per recuperare il paese e i post dai dati:

 query { authors { country, posts { title } } }

La risposta che otterremo dovrebbe contenere i dati JSON dei post del blog con solo il titolo e nient'altro:

 [ { country: “Nigeria”, posts: [{...}, {...}, {...}] }, { country: “Tunisia”, posts: [] }, { title: “Ghana”, posts: []}, ]

Possiamo anche usare argomenti come condizioni per una query:

 query { authors (country: “Nigeria”) { country, posts { title } } }

Che dovrebbe tornare

 [ { country: “Nigeria”, posts: [{...}, {...}, {...}] } ]

I campi nidificati possono anche essere interrogati, come i post con il tipo Post, puoi chiedere solo i titoli:

 query { authors(country: 'Nigeria') { country, posts { title } } }

E dovrebbe restituire qualsiasi tipo di autore corrispondente alla Nigeria che restituisce il paese e invia un array contenente oggetti con solo il campo del titolo.

Gatsby con GraphQL

Per evitare il sovraccarico di avere un server/servizio che serve dati che GraphQL può trasformare, Gatsby esegue query GraphQL in fase di compilazione. I dati vengono forniti ai componenti durante il processo di compilazione, rendendoli prontamente disponibili all'interno del browser senza un server.

Tuttavia, Gatsby può essere eseguito come un server che può essere interrogato da altri client GraphQL, come GraphiQL, in un browser.

Gatsby Modi di interazione con GraphQL

Esistono due luoghi in cui Gatsby può interagire con GraphQL, tramite un file API gatsby-node.js e tramite i componenti della pagina.

gatsby-node.js

L'API createPage può essere configurata come una funzione che riceverà un helper graphql come parte degli elementi nel primo argomento passato alla funzione.

 // gatsby-node.js source: https://www.gatsbyjs.org/docs/node-apis/#createPages exports.createPages = async ({ graphql, actions }) => { const result = await graphql(` query loadPagesQuery ($limit: Int!) { allMarkdownRemark(limit: $limit) { edges { node { frontmatter { slug } } } } }`) }

Nel codice precedente, abbiamo utilizzato l'helper GraphQL per recuperare i file markdown dal livello dati di Gatsby. E possiamo iniettare questo per creare una pagina e modificare i dati esistenti all'interno del livello dati Gatsby.

Componenti della pagina

I componenti della pagina all'interno della directory /pages o i modelli resi dall'azione API createPage possono importare graphql dal modulo gatsby ed esportare una pageQuery . A sua volta, Gatsby inietterebbe nuovi data prop negli oggetti di scena del componente pagina contenente i dati risolti.

 import React from "react"; import { graphql } from "gatsby"; const Page = props => { return
{JSON.stringify(props.data)}
; }; export const pageQuery = graphql` interrogazione { ... } `; esporta pagina predefinita;

In altri componenti

Altri componenti possono importare i componenti graphql e StaticQuery dal modulo gatsby , eseguire il rendering di <StaticQuery/> passando i prop di query che implementano l'helper Graphql ed eseguire il rendering per ottenere i dati restituiti.

 import React from "react"; import { StaticQuery, graphql } from "gatsby"; const Brand = props => { return ( <div> <h1>{data.site.siteMetadata.title}</h1> </div> ); }; const Navbar = props => { return ( <StaticQuery query={graphql` query { site { siteMetadata { title } } } `} render={data => <Brand data={data} {...props} />} /> ); }; export default Navbar;

Costruire un blog di pubblicazione Gatsby moderno e avanzato

In questa sezione illustreremo un processo di creazione di un blog che supporta la codifica, la categorizzazione, l'impaginazione e il raggruppamento di articoli per autori. Utilizzeremo i plug-in dell'ecosistema di Gatsby per introdurre alcune funzionalità e utilizzare la logica nelle query GraphQL per creare un blog dell'editore pronto per le pubblicazioni di più autori.

La versione finale del blog che creeremo la puoi trovare qui, inoltre il codice è ospitato su Github.

Inizializzazione del progetto

Come qualsiasi sito Web di Gatsby, inizializziamo da un dispositivo di avviamento, qui utilizzeremo lo starter avanzato ma modificato per soddisfare il nostro caso d'uso.

Prima clona questo repository Github, cambia il ramo di lavoro in dev-init, quindi esegui npm run develop dalla cartella del progetto per avviare il server di sviluppo che rende il sito disponibile su https://localhost:8000.

 git clone [email protected]:limistah/modern-gatsby-starter.git cd modern-gatsby-starter git checkout dev-init npm install npm run develop

Visitando https://localhost:8000 verrà mostrata la home page predefinita per questo ramo.

Creazione di contenuti per post di blog

È possibile accedere ad alcuni contenuti dei post inclusi nel repository del progetto nel ramo dev-blog-content. L'organizzazione della directory dei contenuti è simile a questa /content/YYYY_MM/DD.md , che raggruppa i post entro il mese creato dell'anno.

Il contenuto del post del blog ha title , date , author , category , tags come argomento principale, che utilizzeremo per distinguere un post ed eseguire ulteriori elaborazioni, mentre il resto del contenuto è il corpo del post.

 title: "Bold Mage" date: "2020-07-12" author: "Tunde Isiaka" category: "tech" tags: - programming - stuff - Ice cream - other --- # Donut I love macaroon chocolate bar Oat cake marshmallow lollipop fruitcake I love jelly-o. Gummi bears cake wafer chocolate bar pie. Marshmallow pastry powder chocolate cake candy chupa chups. Jelly beans powder souffle biscuit pie macaroon chocolate cake. Marzipan lemon drops chupa chups sweet cookie sesame snaps jelly halvah.

Visualizzazione del contenuto del post

Prima di poter eseguire il rendering dei nostri post di Markdown in HTML, dobbiamo eseguire alcune elaborazioni. Innanzitutto, caricare i file nella memoria di Gatsby, analizzare l'MD in HTML, collegare le dipendenze delle immagini e i Mi piace. Per facilitare ciò, utilizzeremo una serie di plugin dell'ecosistema Gatsby.

Possiamo usare questi plugin aggiornando gatsby-config.js alla radice del progetto in modo che assomigli a questo:

 module.exports = { siteMetadata: {}, plugins: [ { resolve: "gatsby-source-filesystem", options: { name: "assets", path: `${__dirname}/static/`, }, }, { resolve: "gatsby-source-filesystem", options: { name: "posts", path: `${__dirname}/content/`, }, }, { resolve: "gatsby-transformer-remark", options: { plugins: [ { resolve: `gatsby-remark-relative-images`, }, { resolve: "gatsby-remark-images", options: { maxWidth: 690, }, }, { resolve: "gatsby-remark-responsive-iframe", }, "gatsby-remark-copy-linked-files", "gatsby-remark-autolink-headers", "gatsby-remark-prismjs", ], }, }, ], };

Abbiamo incaricato gatsby di includere i plugin per aiutarci nell'esecuzione di alcune azioni, in particolare il prelievo di file dalla cartella /static per i file statici e /content per i nostri post sul blog. Inoltre, abbiamo incluso un plug-in del trasformatore di commenti per trasformare tutti i file che terminano con .md o .markdown in un nodo con tutti i campi di commento per il rendering di markdown come HTML.

Infine, abbiamo incluso i plugin nell'operare sui nodi generati da gatsby-transformer-remark .

Implementazione del file API gatsby-config.js

Andando avanti, all'interno di gatsby-node.js nella radice del progetto, possiamo esportare una funzione denominata createPage e avere il contenuto della funzione per utilizzare l'helper graphQL per estrarre i nodi dal livello di contenuto di GatsbyJS.

Il primo aggiornamento di questa pagina includerebbe la garanzia di avere uno slug impostato sui nodi di osservazione MarkDown. Ascolteremo l'API onCreateNode e otterremo il nodo creato per determinare se si tratta di un tipo di MarkdownRemark prima di aggiornare il nodo per includere uno slug e una data di conseguenza.

 const path = require("path"); const _ = require("lodash"); const moment = require("moment"); const config = require("./config"); // Called each time a new node is created exports.onCreateNode = ({ node, actions, getNode }) => { // A Gatsby API action to add a new field to a node const { createNodeField } = actions; // The field that would be included let slug; // The currently created node is a MarkdownRemark type if (node.internal.type === "MarkdownRemark") { // Recall, we are using gatsby-source-filesystem? // This pulls the parent(File) node, // instead of the current MarkdownRemark node const fileNode = getNode(node.parent); const parsedFilePath = path.parse(fileNode.relativePath); if ( Object.prototype.hasOwnProperty.call(node, "frontmatter") && Object.prototype.hasOwnProperty.call(node.frontmatter, "title") ) { // The node is a valid remark type and has a title, // Use the title as the slug for the node. slug = `/${_.kebabCase(node.frontmatter.title)}`; } else if (parsedFilePath.name !== "index" && parsedFilePath.dir !== "") { // File is in a directory and the name is not index // eg content/2020_02/learner/post.md slug = `/${parsedFilePath.dir}/${parsedFilePath.name}/`; } else if (parsedFilePath.dir === "") { // File is not in a subdirectory slug = `/${parsedFilePath.name}/`; } else { // File is in a subdirectory, and name of the file is index // eg content/2020_02/learner/index.md slug = `/${parsedFilePath.dir}/`; } if (Object.prototype.hasOwnProperty.call(node, "frontmatter")) { if (Object.prototype.hasOwnProperty.call(node.frontmatter, "slug")) slug = `/${_.kebabCase(node.frontmatter.slug)}`; if (Object.prototype.hasOwnProperty.call(node.frontmatter, "date")) { const date = moment(new Date(node.frontmatter.date), "DD/MM/YYYY"); if (!date.isValid) console.warn(`WARNING: Invalid date.`, node.frontmatter); // MarkdownRemark does not include date by default createNodeField({ node, name: "date", value: date.toISOString() }); } } createNodeField({ node, name: "slug", value: slug }); } };

L'elenco dei post

A questo punto, possiamo implementare l'API createPages per interrogare tutti i markdown e creare una pagina con il percorso come slug che abbiamo creato sopra. Guardalo su Github.

 //gatsby-node.js // previous code // Create Pages Programatically! exports.createPages = async ({ graphql, actions }) => { // Pulls the createPage action from the Actions API const { createPage } = actions; // Template to use to render the post converted HTML const postPage = path.resolve("./src/templates/singlePost/index.js"); // Get all the markdown parsed through the help of gatsby-source-filesystem and gatsby-transformer-remark const allMarkdownResult = await graphql(` { allMarkdownRemark { edges { node { fields { slug } frontmatter { title tags category date author } } } } } `); // Throws if any error occur while fetching the markdown files if (allMarkdownResult.errors) { console.error(allMarkdownResult.errors); throw allMarkdownResult.errors; } // Items/Details are stored inside of edges const postsEdges = allMarkdownResult.data.allMarkdownRemark.edges; // Sort posts postsEdges.sort((postA, postB) => { const dateA = moment( postA.node.frontmatter.date, siteConfig.dateFromFormat ); const dateB = moment( postB.node.frontmatter.date, siteConfig.dateFromFormat ); if (dateA.isBefore(dateB)) return 1; if (dateB.isBefore(dateA)) return -1; return 0; }); // Pagination Support for posts const paginatedListingTemplate = path.resolve( "./src/templates/paginatedListing/index.js" ); const { postsPerPage } = config; if (postsPerPage) { // Get the number of pages that can be accommodated const pageCount = Math.ceil(postsEdges.length / postsPerPage); // Creates an empty array Array.from({ length: pageCount }).forEach((__value__, index) => { const pageNumber = index + 1; createPage({ path: index === 0 ? `/posts` : `/posts/${pageNumber}/`, component: paginatedListingTemplate, context: { limit: postsPerPage, skip: index * postsPerPage, pageCount, currentPageNumber: pageNumber, }, }); }); } else { // Load the landing page instead createPage({ path: `/`, component: landingPage, }); } };

Nella funzione createPages , utilizziamo l'helper graphql fornito da Gatsby per interrogare i dati dal livello di contenuto. Abbiamo utilizzato una query Graphql standard per eseguire questa operazione e abbiamo passato una query per ottenere contenuto dal tipo allMarkdownRemark . Quindi è andato avanti per ordinare i post in base alla data di creazione.

Abbiamo quindi estratto una proprietà postPerPage da un oggetto di configurazione importato, che viene utilizzato per ridurre i post totali al numero specificato di post per una singola pagina.

Per creare una pagina di elenco che supporti l'impaginazione, è necessario passare il limite, pageNumber e il numero di pagine da saltare al componente che renderebbe l'elenco. Stiamo ottenendo questo utilizzando la proprietà di contesto dell'oggetto di configurazione createPage . Accederemo a queste proprietà dalla pagina per fare un'altra query graphql per recuperare i post entro il limite.

Possiamo anche notare che utilizziamo lo stesso componente del modello per l'elenco e solo il percorso cambia utilizzando l'indice dell'array di blocchi che avevamo definito in precedenza. Gatsby passerà i dati necessari per un determinato URL corrispondente a /{chunkIndex} , quindi possiamo avere / per i primi dieci post e /2 per i prossimi dieci post.

Home page del blog moderno
Home page del blog moderno (anteprima grande)

Rendering dell'elenco dei post

Il componente che esegue il rendering di queste pagine può essere trovato in src/templates/singlePost/index.js della cartella del progetto. Esporta anche un helper graphql che estrae il parametro limit e page query ricevuto dal processo createPages per interrogare gatsby per i post all'interno dell'intervallo della pagina corrente.

 import React from "react"; import { graphql, Link } from "gatsby"; import Layout from "../../layout"; import PostListing from "../../components/PostListing"; import "./index.css"; const Pagination = ({ currentPageNum, pageCount }) => { const prevPage = currentPageNum - 1 === 1 ? "/" : `/${currentPageNum - 1}/`; const nextPage = `/${currentPageNum + 1}/`; const isFirstPage = currentPageNum === 1; const isLastPage = currentPageNum === pageCount; return ( <div className="paging-container"> {!isFirstPage && <Link to={prevPage}>Previous</Link>} {[...Array(pageCount)].map((_val, index) => { const pageNum = index + 1; return ( <Link key={`listing-page-${pageNum}`} to={pageNum === 1 ? "/" : `/${pageNum}/`} > {pageNum} </Link> ); })} {!isLastPage && <Link to={nextPage}>Next</Link>} </div> ); }; export default (props) => { const { data, pageContext } = props; const postEdges = data.allMarkdownRemark.edges; const { currentPageNum, pageCount } = pageContext; return ( <Layout> <div className="listing-container"> <div className="posts-container"> <PostListing postEdges={postEdges} /> </div> <Pagination pageCount={pageCount} currentPageNum={currentPageNum} /> </div> </Layout> ); }; /* eslint no-undef: "off" */ export const pageQuery = graphql` query ListingQuery($skip: Int!, $limit: Int!) { allMarkdownRemark( sort: { fields: [fields___date], order: DESC } limit: $limit skip: $skip ) { edges { node { fields { slug date } excerpt timeToRead frontmatter { title tags author category date } } } } } `;

La pagina dei post

Per visualizzare il contenuto di una pagina, è necessario creare la pagina in modo programmatico all'interno del file API gatsby-node.js . Innanzitutto, dobbiamo definire un nuovo componente con cui eseguire il rendering del contenuto, per questo abbiamo src/templates/singlePost/index.jsx .

 import React from "react"; import { graphql, Link } from "gatsby"; import _ from "lodash"; import Layout from "../../layout"; import "./b16-tomorrow-dark.css"; import "./index.css"; import PostTags from "../../components/PostTags"; export default class PostTemplate extends React.Component { render() { const { data, pageContext } = this.props; const { slug } = pageContext; const postNode = data.markdownRemark; const post = postNode.frontmatter; if (!post.id) { post.id = slug; } return ( <Layout> <div> <div> <h1>{post.title}</h1> <div className="category"> Posted to{" "} <em> <Link key={post.category} style={{ textDecoration: "none" }} to={`/category/${_.kebabCase(post.category)}`} > <a>{post.category}</a> </Link> </em> </div> <PostTags tags={post.tags} /> <div dangerouslySetInnerHTML={{ __html: postNode.html }} /> </div> </div> </Layout> ); } } /* eslint no-undef: "off" */ export const pageQuery = graphql` query BlogPostBySlug($slug: String!) { markdownRemark(fields: { slug: { eq: $slug } }) { html timeToRead excerpt frontmatter { title date category tags } fields { slug date } } } `;

Ancora una volta, stiamo usando un helper graphQL per estrarre una pagina da una query slug che verrebbe inviata alla pagina tramite l'API createPages.

Successivamente, dovremmo aggiungere il codice seguente a gatsby-node.js alla fine della funzione API createPages .

 // Template to use to render the post converted HTML const postPage = path.resolve("./src/templates/singlePost/index.jsx"); // Loops through all the post nodes postsEdges.forEach((edge, index) => { // Create post pages createPage({ path: edge.node.fields.slug, component: postPage, context: { slug: edge.node.fields.slug, }, }); });

E potremmo visitare '/{pageSlug}' e fare in modo che visualizzi il contenuto del file markdown per quella pagina come HTML. Ad esempio, https://localhost:8000/the-butterfly-of-the-edge dovrebbe caricare l'HTML convertito per il markdown su: content/2020_05/01.md , simile a tutti gli slug validi. Grande!

Pagina del post sul blog moderno
Pagina del post del blog moderno (anteprima grande)

Categorie e tag di rendering

Il componente del modello di post singolo ha un collegamento a una pagina nel formato /categories/{categoryName} per elencare i post con categorie simili.

Possiamo prima catturare tutte le categorie e i tag mentre costruiamo la singola pagina del post nel file gatsby-node.js , quindi creiamo pagine per ogni categoria/tag catturato passando il nome della categoria/tag.

Una modifica alla sezione per la creazione di una singola pagina di post in gatsby-node.js è simile alla seguente:

 const categorySet = new Set(); const tagSet = new Set(); const categoriesListing = path.resolve( "./src/templates/categoriesListing/index.jsx" ); // Template to use to render posts based on categories const tagsListingPage = path.resolve("./src/templates/tagsListing/index.jsx"); // Loops through all the post nodes postsEdges.forEach((edge, index) => { // Generate a list of categories if (edge.node.frontmatter.category) { categorySet.add(edge.node.frontmatter.category); } // Generate a list of tags if (edge.node.frontmatter.tags) { edge.node.frontmatter.tags.forEach((tag) => { tagSet.add(tag); }); } // Create post pages createPage({ path: edge.node.fields.slug, component: postPage, context: { slug: edge.node.fields.slug, }, }); });

E all'interno del componente per elencare i post per tag, possiamo avere la query di esportazione pageQuery graphql per i post, incluso quel tag nel suo elenco di tag. Useremo la funzione filter di graphql e l'operatore $in per ottenere questo:

 // src/templates/tagsListing/ import React from "react"; import { graphql } from "gatsby"; import Layout from "../../layout"; import PostListing from "../../components/PostListing"; export default ({ pageContext, data }) => { const { tag } = pageContext; const postEdges = data.allMarkdownRemark.edges; return ( <Layout> <div className="tag-container"> <div>Posts posted with {tag}</div> <PostListing postEdges={postEdges} /> </div> </Layout> ); }; /* eslint no-undef: "off" */ export const pageQuery = graphql` query TagPage($tag: String) { allMarkdownRemark( limit: 1000 sort: { fields: [fields___date], order: DESC } filter: { frontmatter: { tags: { in: [$tag] } } } ) { totalCount edges { node { fields { slug date } excerpt timeToRead frontmatter { title tags author date } } } } } `;

E abbiamo lo stesso processo nel componente di elenco delle categorie, e la differenza è che dobbiamo solo trovare dove le categorie corrispondono esattamente a ciò che gli passiamo.

 // src/templates/categoriesListing/index.jsx import React from "react"; import { graphql } from "gatsby"; import Layout from "../../layout"; import PostListing from "../../components/PostListing"; export default ({ pageContext, data }) => { const { category } = pageContext; const postEdges = data.allMarkdownRemark.edges; return ( <Layout> <div className="category-container"> <div>Posts posted to {category}</div> <PostListing postEdges={postEdges} /> </div> </Layout> ); }; /* eslint no-undef: "off" */ export const pageQuery = graphql` query CategoryPage($category: String) { allMarkdownRemark( limit: 1000 sort: { fields: [fields___date], order: DESC } filter: { frontmatter: { category: { eq: $category } } } ) { totalCount edges { node { fields { slug date } excerpt timeToRead frontmatter { title tags author date } } } } } `;

È evidente che all'interno di entrambi i componenti dei tag e delle categorie, vengono visualizzati i collegamenti alla pagina del singolo post per ulteriori letture del contenuto di un post.

Pagina di post singolo Hello World con tag
Post moderno con categoria taggata (Anteprima grande)

Aggiunta del supporto per gli autori

Per supportare più autori, dobbiamo apportare alcune modifiche al contenuto del nostro post e introdurre nuovi concetti.

Carica file JSON

Innanzitutto, dovremmo essere in grado di archiviare il contenuto degli autori in un file JSON come questo:

 { "mdField": "aleem", "name": "Aleem Isiaka", "email": "[email protected]", "location": "Lagos, Nigeria", "avatar": "https://api.adorable.io/avatars/55/[email protected]", "description": "Yeah, I like animals better than people sometimes... Especially dogs. Dogs are the best. Every time you come home, they act like they haven't seen you in a year. And the good thing about dogs... is they got different dogs for different people.", "userLinks": [ { "label": "GitHub", "url": "https://github.com/limistah/modern-gatsby-starter", "iconClassName": "fa fa-github" }, { "label": "Twitter", "url": "https://twitter.com/limistah", "iconClassName": "fa fa-twitter" }, { "label": "Email", "url": "mailto:[email protected]", "iconClassName": "fa fa-envelope" } ] }

Li memorizzeremmo nella directory di un autore nella radice del nostro progetto come /authors . Si noti che l'autore JSON ha mdField che sarebbe l'identificatore univoco del campo dell'autore che introdurremo nel contenuto del blog di markdown; ciò garantisce che gli autori possano avere più profili.

Successivamente, dobbiamo aggiornare i plug-in gatsby-config.js gatsby-source-filesystem di caricare il contenuto dalla directory authors/ nel nodo File.

 // gatsby-config.js { resolve: `gatsby-source-filesystem`, options: { name: "authors", path: `${__dirname}/authors/`, }, }

Infine, installeremo gatsby-transform-json per trasformare i file JSON creati per una facile gestione e una corretta elaborazione.

 npm install gatsby-transformer-json --save

E includilo nei plugin di gatsby-config.js ,

 module.exports = { plugins: [ // ...other plugins `gatsby-transformer-json` ], };

Interrogazione e creazione della pagina degli autori

Per cominciare, dobbiamo interrogare tutti gli autori nella nostra directory authors/ all'interno di gatsby-config.js che sono stati caricati nel livello dati, dovremmo aggiungere il codice seguente per createPages la funzione API di pagine

 const authorsListingPage = path.resolve( "./src/templates/authorsListing/index.jsx" ); const allAuthorsJson = await graphql(` { allAuthorsJson { edges { node { id avatar mdField location name email description userLinks { iconClassName label url } } } } } `); const authorsEdges = allAuthorsJson.data.allAuthorsJson.edges; authorsEdges.forEach((author) => { createPage({ path: `/authors/${_.kebabCase(author.node.mdField)}/`, component: authorsListingPage, context: { authorMdField: author.node.mdField, authorDetails: author.node, }, }); });

In questo frammento di codice, estraiamo tutti gli autori dal tipo allAuthorsJson, quindi richiamiamo forEach sui nodi per creare una pagina in cui passiamo mdField per distinguere l'autore e authorDetails per informazioni complete sull'autore.

Rendering dei post dell'autore

Nel componente che rende la pagina che può essere trovata in src/templates/authorsListing/index.jsx , abbiamo il contenuto seguente per il file

 import React from "react"; import { graphql } from "gatsby"; import Layout from "../../layout"; import PostListing from "../../components/PostListing"; import AuthorInfo from "../../components/AuthorInfo"; export default ({ pageContext, data }) => { const { authorDetails } = pageContext; const postEdges = data.allMarkdownRemark.edges; return ( <Layout> <div> <h1 style={{ textAlign: "center" }}>Author Roll</h1> <div className="category-container"> <AuthorInfo author={authorDetails} /> <PostListing postEdges={postEdges} /> </div> </div> </Layout> ); }; /* eslint no-undef: "off" */ export const pageQuery = graphql` query AuthorPage($authorMdField: String) { allMarkdownRemark( limit: 1000 sort: { fields: [fields___date], order: DESC } filter: { frontmatter: { author: { eq: $authorMdField } } } ) { totalCount edges { node { fields { slug date } excerpt timeToRead frontmatter { title tags author date } } } } } `;

Nel codice sopra, abbiamo esportato pageQuery come facciamo noi, per creare una query GraphQL per recuperare i post corrispondenti a un autore, stiamo usando l'operatore $eq per ottenere ciò stiamo generando collegamenti a una singola pagina di post per ulteriori letture.

Pagina dell'autore del blog moderno
Pagina dell'autore del blog moderno (anteprima grande)

Conclusione

In Gatsby, possiamo interrogare qualsiasi dato esistente all'interno del suo livello di accesso ai dati con l'uso della query GraphQL e passare variabili utilizzando alcuni costrutti definiti dall'architettura di Gatsby. abbiamo visto come potremmo utilizzare l'helper graphql in vari luoghi e comprendere i modelli ampiamente utilizzati per interrogare i dati nei siti Web di Gatsby con l'aiuto di GraphQL.

GraphQL è molto potente e potrebbe fare altre cose come la mutazione dei dati su un server. Gatsby non ha bisogno di aggiornare i suoi dati in fase di esecuzione, quindi non supporta la funzione di mutazione di GraphQL.

GraphQL è una grande tecnologia e Gatsby la rende molto interessante da usare nel loro framework.

Riferimenti

  • Supporto Gatsby per GraphQL
  • Perché Gatsby usa GraphQL
  • Concetti di GraphQL in Gatsby
  • Come GraphQL: concetti di base
  • Linguaggio di definizione dello schema in GraphQL
  • Un'introduzione a GraphQL
  • Starter avanzato Gatsby