Utilizare avansată GraphQL pe site-urile Gatsby
Publicat: 2022-03-10Înainte de lansarea GraphQL în 2015, Transferul de stat reprezentativ (REST) a fost principala modalitate de interfață cu un API. Prin urmare, introducerea GraphQL a fost o schimbare majoră în dezvoltarea software-ului.
Ca generator modern de site-uri static, Gatsby folosește GraphQL pentru a oferi o metodologie concisă pentru introducerea și manipularea datelor în cadru. În acest articol, vom arunca o privire mai atentă asupra GraphQL și asupra modului în care îl putem integra într-un site web Gatsby prin construirea și implementarea aprovizionării și transformării avansate de date în Gatsby. Rezultatul este blogul unui editor care ar putea fi folosit de orice firmă de editură pentru a partaja conținutul autorilor lor.
Ce este GraphQL?
Mergând după QL în numele său, GraphQL este un limbaj de interogare combinat cu un set de instrumente create pentru a oferi flexibilitate și eficiență în modul în care extragem datele dintr-o sursă. Cu GraphQL, un client/consumator poate solicita exact datele de care are nevoie. Serverul/furnizorul răspunde cu o semnătură de răspuns JSON care corespunde cerințelor specificate în interogare. Ne permite să ne exprimăm nevoile de date în mod declarativ.
De ce să folosiți GraphQL?
Ca generator de site-uri static, Gatsby stochează fișiere statice, ceea ce face ca interogarea datelor să fie aproape imposibilă. Există adesea componente ale paginii care trebuie să fie dinamice, cum ar fi pagina cu o singură postare de blog, așa că ar apărea nevoia de a extrage date dintr-o sursă și de a le transforma în formatul necesar, la fel ca postările de blog stocate în fișiere de reducere. Unele plugin-uri oferă date din diverse surse, ceea ce vă lasă să interogați și să transformați datele necesare dintr-o sursă.
Conform unei liste de pe gatsby.org, GraphQL este util în Gatsby pentru:
- Eliminați boilerplate
- Împingeți complexitățile frontend în interogări
- Oferiți o soluție perfectă pentru datele mereu complexe ale unei aplicații moderne
- În cele din urmă, pentru a elimina balonarea codului, îmbunătățind astfel performanța.
Concepte GraphQL
Gatsby menține aceleași idei ale GraphQL ca cele utilizate pe scară largă; unele dintre aceste concepte sunt:
Limbajul de definire a schemei
GraphQL SDL este un sistem de tip încorporat în GraphQL și îl puteți utiliza pentru a crea noi tipuri pentru datele dvs.
Putem declara un tip pentru o țară, iar atributele acesteia ar putea include un nume, continent, populație, pib și număr de state.
Ca exemplu de mai jos, am creat un nou tip cu numele Aleem . Are hobbies
care sunt o serie de șiruri și nu sunt necesare, dar sunt necesare țara, starea civilă și postările din cauza ! acestea includ, de asemenea postări referințe alt tip, 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 }
Întrebări
Putem folosi Interogări pentru a extrage date dintr-o sursă GraphQL.
Luând în considerare un set de date ca cel de mai jos
{ 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", }, ], }, ], }, };
Putem avea o interogare care să preia țara și postările din date:
query { authors { country, posts { title } } }
Răspunsul pe care îl vom primi ar trebui să conțină date JSON ale postărilor de blog doar cu titlul și nimic mai mult:
[ { country: “Nigeria”, posts: [{...}, {...}, {...}] }, { country: “Tunisia”, posts: [] }, { title: “Ghana”, posts: []}, ]
De asemenea, putem folosi argumente ca condiții pentru o interogare:
query { authors (country: “Nigeria”) { country, posts { title } } }
Care ar trebui să se întoarcă
[ { country: “Nigeria”, posts: [{...}, {...}, {...}] } ]
Câmpurile imbricate pot fi, de asemenea, interogate, cum ar fi postările cu tipul Postare, puteți cere doar titlurile:
query { authors(country: 'Nigeria') { country, posts { title } } }
Și ar trebui să returneze orice tip de autor care se potrivește cu Nigeria , returnând țara și postează matricea care conține obiecte doar cu câmpul titlu.
Gatsby cu GraphQL
Pentru a evita suprasolicitarea de a avea un server/serviciu care servește date pe care GraphQL le poate transforma, Gatsby execută interogări GraphQL în timpul construirii. Datele sunt furnizate componentelor în timpul procesului de construire, făcându-le disponibile în browser fără un server.
Totuși, Gatsby poate rula ca un server care poate fi interogat de alți clienți GraphQL, cum ar fi GraphiQL, într-un browser.
Gatsby Modalități de a interacționa cu GraphQL
Există două locuri în care Gatsby poate interacționa cu GraphQL, printr-un fișier API gatsby-node.js și prin componentele paginii.
gatsby-node.js
API-ul createPage poate fi configurat ca o funcție care va primi un ajutor graphql
ca parte a elementelor din primul argument transmis funcției.
// 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 } } } } }`) }
În codul de mai sus, am folosit ajutorul GraphQL pentru a prelua fișierele de reducere din stratul de date al lui Gatsby. Și putem injecta acest lucru pentru a crea o pagină și a modifica datele existente în stratul de date Gatsby.
Componentele paginii
Componentele paginii din directorul /pages sau șabloanele redate prin acțiunea API createPage
pot importa graphql
din modulul gatsby
și pot exporta un pageQuery
. La rândul său, Gatsby ar injecta o nouă data
de recuzită în elementele de recuzită ale componentei paginii care conține datele rezolvate.
import React from "react"; import { graphql } from "gatsby"; const Page = props => { return
{JSON.stringify(props.data)}; }; export const pageQuery = graphql` interogare { ... } `; exporta pagina implicită;
În Alte Componente
Alte componente pot importa componente graphql
și StaticQuery
din modulul gatsby
, pot reda elementele de sprijin de interogare <StaticQuery/>
care implementează ajutorul Graphql și pot randa pentru a obține datele returnate.
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;
Construirea unui blog modern și avansat de editori Gatsby
În această secțiune vom parcurge un proces de creare a unui blog care acceptă etichetarea, clasificarea, paginarea și gruparea articolelor după autori. Vom folosi pluginuri ale ecosistemului lui Gatsby pentru a aduce unele caracteristici și vom folosi logici în interogările GraphQL pentru a crea un blog al editorului care este gata pentru publicații cu mai mulți autori.
Versiunea finală a blogului pe care o vom construi poate fi găsită aici, de asemenea, codul este găzduit pe Github.
Inițializarea Proiectului
Ca orice site web Gatsby, inițializam de la un starter, aici vom folosi starterul avansat, dar modificat pentru a satisface cazul nostru de utilizare.
Mai întâi clonează acest depozit Github, schimbă ramura de lucru în dev-init și apoi rulează npm run develop
din folderul proiectului pentru a porni serverul de dezvoltare, făcând site-ul disponibil la 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
Vizitarea https://localhost:8000 va afișa pagina de pornire implicită pentru această ramură.
Crearea conținutului postărilor de blog
O parte din conținutul postărilor inclus în depozitul de proiect ar putea fi accesat la filiala dev-blog-content. Organizarea directorului de conținut arată astfel /content/YYYY_MM/DD.md
, care grupează postările după luna creată a unui an.
Conținutul postării de pe blog are title
, date
, author
, category
, tags
ca subiect principal, pe care le vom folosi pentru a distinge o postare și pentru a face unele procesări ulterioare, în timp ce restul conținutului este corpul postării.
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.
Afișarea conținutului postării
Înainte de a putea reda postările noastre Markdown în HTML, trebuie să facem o procesare. În primul rând, încărcarea fișierelor în spațiul de stocare Gatsby, analizarea MD-ului în HTML, legarea dependențelor de imagine și a like-urilor. Pentru a ușura acest lucru, vom folosi o serie de pluginuri ale ecosistemului Gatsby.
Putem folosi aceste pluginuri actualizând gatsby-config.js la rădăcina proiectului, astfel încât să arate astfel:
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", ], }, }, ], };
Am instruit gatsby să includă pluginuri care să ne ajute în efectuarea unor acțiuni, în special extragerea fișierelor din folderul /static pentru fișiere statice și /conținut pentru postările noastre de blog. De asemenea, am inclus un plugin de transformare a observațiilor pentru a transforma toate fișierele care se termină cu .md sau .markdown într-un nod cu toate câmpurile de remarcă pentru redarea markdown ca HTML.
În cele din urmă, am inclus pluginuri în operarea pe nodurile generate de gatsby-transformer-remark
.
Implementarea fișierului API gatsby-config.js
Mergând înainte, în interiorul gatsby-node.js din rădăcina proiectului, putem exporta o funcție numită createPage
și putem avea conținutul funcției pentru a folosi ajutorul graphQL pentru a extrage noduri din stratul de conținut al GatsbyJS.
Prima actualizare a acestei pagini ar include asigurarea că avem un slug setat pe nodurile de observații MarkDown. Vom asculta API-ul onCreateNode și vom crea nodul pentru a determina dacă este un tip de MarkdownRemark înainte de a actualiza nodul pentru a include un slug și o dată în consecință.
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 }); } };
Lista de postare
În acest moment, putem implementa API-ul createPages
pentru a interoga toate reducerile și pentru a crea o pagină cu calea ca slug-ul creat mai sus. Vezi pe 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, }); } };
În funcția createPages
, folosim ajutorul graphql
oferit de Gatsby pentru a interoga datele din stratul de conținut. Am folosit o interogare standard Graphql pentru a face acest lucru și am transmis o interogare pentru a obține conținut de la toate tipurile allMarkdownRemark
. Apoi a mers înainte pentru a sorta postările după data creată.
Apoi am extras o proprietate postPerPage
dintr-un obiect de configurare importat, care este folosit pentru a reduce totalul postărilor la numărul specificat de postări pentru o singură pagină.
Pentru a crea o pagină de listare care acceptă paginarea, trebuie să trecem limita, pageNumber și numărul de pagini pe care să trecem la componenta care ar randa lista. Reușim acest lucru folosind proprietatea context a obiectului de configurare createPage
. Vom accesa aceste proprietăți din pagină pentru a face o altă interogare graphql pentru a prelua postări în limita limită.
De asemenea, putem observa că folosim aceeași componentă șablon pentru listare și doar calea se schimbă utilizând indexul matricei de bucăți pe care l-am definit mai înainte. Gatsby va transmite datele necesare pentru o anumită adresă URL care se potrivește cu /{chunkIndex}
, astfel încât să putem avea /
pentru primele zece postări și /2
pentru următoarele zece postări.
Redarea Post Listing
Componenta care redă aceste pagini poate fi găsită la src/templates/singlePost/index.js
din folderul proiectului. De asemenea, exportă un ajutor graphql
care extrage limita și parametrul de interogare a paginii pe care l-a primit din procesul createPages pentru a interoga pe gatsby postări în intervalul paginii curente.
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 } } } } } `;
Pagina de postare
Pentru a vizualiza conținutul unei pagini, trebuie să creăm programatic pagina în interiorul fișierului API gatsby-node.js
. În primul rând, trebuie să definim o nouă componentă cu care să redăm conținutul, pentru aceasta avem 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 } } } `;
Din nou, folosim un ajutor graphQL pentru a scoate o pagină printr-o interogare slug care ar fi trimisă către pagină prin intermediul API-ului createPages.
În continuare, ar trebui să avem codul de mai jos adăugat la gatsby-node.js la sfârșitul funcției createPages
API.
// 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, }, }); });
Și am putea vizita „/{pageSlug}” și am putea să redă conținutul fișierului de reducere a paginii respective ca HTML. De exemplu, https://localhost:8000/the-butterfly-of-the-edge ar trebui să încarce HTML convertit pentru markdown la: content/2020_05/01.md
, similar cu toate slug-urile valide. Grozav!
Redarea categoriilor și etichetelor
Componenta șablon de postare unică are un link către o pagină în formatul /categories/{categoryName}
pentru a lista postări cu categorii similare.
Putem prinde mai întâi toate categoriile și etichetele pe măsură ce construim pagina de postare unică în fișierul gatsby-node.js
, apoi cream pagini pentru fiecare categorie/etichetă prinsă care trece numele categoriei/etichetei.
O modificare a secțiunii pentru crearea unei pagini de postare unică în gatsby-node.js arată astfel:
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, }, }); });
Și în cadrul componentei pentru listarea postărilor după etichete, putem avea interogarea de export pageQuery
graphql pentru postări, inclusiv acea etichetă în lista de etichete. Vom folosi funcția de filter
a lui graphql și operatorul $in pentru a realiza acest lucru:
// 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 } } } } } `;
Și avem același proces în componenta de listare a categoriilor, iar diferența este că trebuie doar să găsim unde categoriile se potrivesc exact cu ceea ce îi transmitem.
// 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 } } } } } `;
De remarcat, în ambele componente de etichete și categorii, redăm link-uri către pagina cu o singură postare pentru citirea în continuare a conținutului unei postări.
Adăugarea suportului pentru autori
Pentru a sprijini mai mulți autori, trebuie să facem câteva modificări conținutului postării noastre și să introducem noi concepte.
Încărcați fișiere JSON
În primul rând, ar trebui să putem stoca conținutul autorilor într-un fișier JSON, astfel:
{ "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" } ] }
Le-am stoca într-un director al autorului în rădăcina proiectului nostru ca /authors
. Observați că autorul JSON are mdField
, care ar fi identificatorul unic al câmpului autorului pe care îl vom introduce în conținutul blogului markdown; acest lucru asigură că autorii pot avea mai multe profiluri.
În continuare, trebuie să actualizăm pluginurile gatsby-config.js
indică gatsby-source-filesystem
să încarce conținutul din directorul authors/
în nodul Fișiere.
// gatsby-config.js { resolve: `gatsby-source-filesystem`, options: { name: "authors", path: `${__dirname}/authors/`, }, }
În cele din urmă, vom instala gatsby-transform-json
pentru a transforma fișierele JSON create pentru o manipulare ușoară și o procesare adecvată.
npm install gatsby-transformer-json --save
Și includeți-l în pluginurile pentru gatsby-config.js
,
module.exports = { plugins: [ // ...other plugins `gatsby-transformer-json` ], };
Interogarea și crearea paginii autorilor
Pentru început, trebuie să interogăm toți autorii din directorul nostru authors/
din interiorul gatsby-config.js
care au fost încărcați în stratul de date, ar trebui să atașăm codul de mai jos la funcția createPages
API
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, }, }); });
În acest fragment, extragem toți autorii din tipul allAuthorsJson, apoi, chemând pentru fiecare pe noduri pentru a crea o pagină în care trecem mdField
pentru a distinge autorul și autorul authorDetails
pentru informații complete despre autor.
Redarea postărilor autorului
În componenta care redă pagina care poate fi găsită la src/templates/authorsListing/index.jsx
, avem conținutul de mai jos pentru fișier
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 } } } } } `;
În codul de mai sus, am exportat pageQuery
așa cum facem noi, pentru a crea o interogare GraphQL pentru a prelua postările potrivite de un autor, utilizăm operatorul $eq
pentru a realiza acest lucru, generăm link-uri către o singură pagină de postare pentru citire ulterioară.
Concluzie
În Gatsby, putem interoga orice date care există în stratul său de acces la date cu ajutorul interogării GraphQL și putem trece variabile folosind unele constructe definite de arhitectura lui Gatsby. am văzut cum am putea folosi ajutorul graphql
în diferite locuri și să înțelegem modele utilizate pe scară largă pentru interogarea datelor pe site-urile lui Gatsby cu ajutorul GraphQL.
GraphQL este foarte puternic și poate face alte lucruri, cum ar fi mutarea datelor pe un server. Gatsby nu are nevoie să-și actualizeze datele în timpul execuției, așa că nu acceptă caracteristica de mutație a GraphQL.
GraphQL este o tehnologie excelentă, iar Gatsby o face foarte interesantă de utilizat în cadrul lor.
Referințe
- Suport Gatsby pentru GraphQL
- De ce folosește Gatsby GraphQL
- Concepte GraphQL în Gatsby
- Cum să GraphQL: Concepte de bază
- Limbajul de definire a schemei în GraphQL
- O introducere în GraphQL
- Gatsby Advanced Starter