Uso avanzado de GraphQL en sitios web de Gatsby

Publicado: 2022-03-10
Resumen rápido ↬ En este artículo, Aleem Isiaka explica qué son las construcciones de consulta de GraphQL y cómo se pueden usar para interactuar con la capa de acceso a datos de un sitio web de Gatsby. Echemos un vistazo a algunos de los casos de uso avanzados de GraphQL dentro de un sitio web de Gatsby mediante el uso de datos coincidentes de diferentes fuentes.

Antes del lanzamiento de GraphQL en 2015, la transferencia de estado representacional (REST) ​​era la forma principal de interactuar con una API. Por lo tanto, la introducción de GraphQL supuso un cambio importante en el desarrollo de software.

Como generador de sitios estáticos modernos, Gatsby aprovecha GraphQL para proporcionar una metodología concisa para incorporar y manipular datos en el marco. En este artículo, analizaremos más de cerca GraphQL y cómo podemos integrarlo en un sitio web de Gatsby mediante la creación e implementación de fuentes y transformaciones de datos avanzadas en Gatsby. El resultado es un blog de editor que podría ser utilizado por cualquier editorial para compartir contenido de sus autores.

¿Qué es GraphQL?

Con el QL en su nombre, GraphQL es un lenguaje de consulta combinado con un conjunto de herramientas creadas para proporcionar flexibilidad y eficiencia en la forma en que extraemos datos de una fuente. Con GraphQL, un cliente/consumidor puede solicitar exactamente los datos que necesita. El servidor/proveedor responde con una firma de respuesta JSON que coincide con los requisitos especificados en la consulta. Nos permite expresar nuestras necesidades de datos de forma declarativa.

¿Por qué usar GraphQL?

Como generador de sitios estáticos, Gatsby almacena archivos estáticos, lo que hace que la consulta de datos sea casi imposible. A menudo, hay componentes de página que tienen que ser dinámicos, como la página de publicación de blog única, por lo que surgiría la necesidad de extraer datos de una fuente y transformarlos al formato necesario, al igual que tener publicaciones de blog almacenadas en archivos de rebajas. Algunos complementos proporcionan datos de varias fuentes, lo que le permite consultar y transformar los datos necesarios de una fuente.

Según una lista en gatsby.org, GraphQL es útil en Gatsby para:

  • Eliminar repetitivo
  • Empuje las complejidades de la interfaz de usuario en las consultas
  • Proporcione una solución perfecta para los datos siempre complejos de una aplicación moderna
  • Finalmente, para eliminar la sobrecarga de código, mejorando así el rendimiento.

Conceptos de GraphQL

Gatsby mantiene las mismas ideas de GraphQL tan ampliamente utilizadas; algunos de estos conceptos son:

Lenguaje de definición de esquemas

GraphQL SDL es un sistema de tipos incorporado en GraphQL y puede usarlo para crear nuevos tipos para sus datos.

Podemos declarar un tipo para un país, y sus atributos podrían incluir un nombre, continente, población, pib y número de estados.

Como ejemplo a continuación, hemos creado un nuevo tipo con el nombre de Aleem . Tiene hobbies que son una variedad de cadenas y no son obligatorios, pero se necesitan país, estado civil y publicaciones debido a la ! incluyen, también publicaciones referencias a otro tipo, Publicar .

 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 }

Consultas

Podemos usar Consultas para extraer datos de una fuente de GraphQL.

Considerando un conjunto de datos como el siguiente

 { 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", }, ], }, ], }, };

Podemos tener una consulta para obtener el país y las publicaciones de los datos:

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

La respuesta que obtendremos debe contener datos JSON de publicaciones de blog con solo el título y nada más:

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

También podemos usar argumentos como condiciones para una consulta:

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

que debe volver

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

Los campos anidados también se pueden consultar, como las publicaciones con el tipo de publicación, puede solicitar solo los títulos:

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

Y debería devolver cualquier tipo de Autor que coincida con Nigeria , devolviendo el país y la matriz de publicaciones que contiene objetos con solo el campo de título.

Gatsby con GraphQL

Para evitar la sobrecarga de tener un servidor/servicio que sirve datos que GraphQL puede transformar, Gatsby ejecuta consultas de GraphQL en el momento de la compilación. Los datos se proporcionan a los componentes durante el proceso de compilación, lo que los hace fácilmente disponibles dentro del navegador sin un servidor.

Aún así, Gatsby puede ejecutarse como un servidor que puede ser consultado por otros clientes de GraphQL, como GraphiQL, en un navegador.

Formas Gatsby de interactuar con GraphQL

Hay dos lugares donde Gatsby puede interactuar con GraphQL, a través de un archivo API gatsby-node.js y a través de componentes de página.

gatsby-node.js

La API createPage se puede configurar como una función que recibirá un ayudante de graphql como parte de los elementos en el primer argumento pasado a la función.

 // 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 } } } } }`) }

En el código anterior, hemos utilizado el ayudante de GraphQL para obtener archivos de descuento de la capa de datos de Gatsby. Y podemos inyectar esto para crear una página y modificar los datos existentes dentro de la capa de datos de Gatsby.

Componentes de la página

Los componentes de la página dentro del directorio /pages o las plantillas representadas por la acción de la API createPage pueden importar graphql desde el módulo gatsby y exportar una pageQuery de página. A su vez, Gatsby inyectaría nuevos data apoyo en los accesorios del componente de la página que contiene los datos resueltos.

 import React from "react"; import { graphql } from "gatsby"; const Page = props => { return
{JSON.stringify(accesorios.datos)}
; }; export const pageQuery = graphql` consulta { ... } `; exportar página predeterminada;

En Otros Componentes

Otros componentes pueden importar componentes graphql y StaticQuery desde el módulo gatsby , renderizar <StaticQuery/> pasando accesorios de consulta que implementan el ayudante de Graphql y renderizar para obtener los datos devueltos.

 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;

Creación de un blog de Gatsby Publishing moderno y avanzado

En esta sección, recorreremos un proceso de creación de un blog que admita el etiquetado, la categorización, la paginación y la agrupación de artículos por autores. Usaremos complementos del ecosistema de Gatsby para incorporar algunas características y usar lógicas en las consultas de GraphQL para hacer que el blog de un editor esté listo para publicaciones de varios autores.

La versión final del blog que construiremos se puede encontrar aquí, también el código está alojado en Github.

Inicializar el proyecto

Como cualquier sitio web de Gatsby, inicializamos desde un iniciador, aquí usaremos el iniciador avanzado pero modificado para atender nuestro caso de uso.

Primero clone este repositorio de Github, cambie la rama de trabajo a dev-init y luego ejecute npm run develop desde la carpeta del proyecto para iniciar el servidor de desarrollo y hacer que el sitio esté disponible en 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

Visitar https://localhost:8000 mostrará la página de inicio predeterminada para esta sucursal.

Creación de contenido de publicaciones de blog

Se puede acceder a parte del contenido de las publicaciones incluido en el repositorio del proyecto en la rama dev-blog-content. La organización del directorio de contenido se ve así /content/YYYY_MM/DD.md , que agrupa las publicaciones por el mes creado del año.

El contenido de la publicación del blog tiene el title , la date , el author , category y las tags como tema principal, que usaremos para distinguir una publicación y realizar un procesamiento posterior, mientras que el resto del contenido es el cuerpo de la publicación.

 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.

Visualización del contenido de la publicación

Antes de que podamos representar nuestras publicaciones de Markdown en HTML, tenemos que hacer un poco de procesamiento. Primero, cargar los archivos en el almacenamiento de Gatsby, analizar el MD en HTML, vincular las dependencias de imágenes y los "me gusta". Para facilitar esto, utilizaremos una gran cantidad de complementos del ecosistema Gatsby.

Podemos usar estos complementos actualizando gatsby-config.js en la raíz del proyecto para que se vea así:

 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", ], }, }, ], };

Hemos dado instrucciones a Gatsby para que incluya complementos que nos ayuden a realizar algunas acciones, en particular, extraer archivos de la carpeta /static para archivos estáticos y /content para nuestras publicaciones de blog. Además, hemos incluido un complemento transformador de comentarios para transformar todos los archivos que terminan en .md o .markdown en un nodo con todos los campos de comentarios para representar el marcado como HTML.

Por último, incluimos complementos para operar en los nodos generados por gatsby-transformer-remark .

Implementando el archivo API gatsby-config.js

En el futuro, dentro de gatsby-node.js en la raíz del proyecto, podemos exportar una función llamada createPage y tener el contenido de la función para usar el ayudante de graphQL para extraer nodos de la capa de contenido de GatsbyJS.

La primera actualización de esta página incluiría garantizar que tengamos un conjunto de slug en los nodos de comentarios de MarkDown. Escucharemos la API onCreateNode y crearemos el nodo para determinar si es un tipo de MarkdownRemark antes de actualizar el nodo para incluir un slug y la fecha correspondiente.

 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 }); } };

El listado de publicaciones

En este punto, podemos implementar la API createPages para consultar todas las rebajas y crear una página con la ruta como el slug que hemos creado anteriormente. Véalo en 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, }); } };

En la función createPages , usamos el ayudante de graphql proporcionado por Gatsby para consultar datos de la capa de contenido. Usamos una consulta Graphql estándar para hacer esto y pasamos una consulta para obtener contenido del tipo allMarkdownRemark . Luego avanzó para ordenar las publicaciones por fecha de creación.

Luego extrajimos una propiedad postPerPage de un objeto de configuración importado, que se usa para dividir el total de publicaciones en el número especificado de publicaciones para una sola página.

Para crear una página de lista que admita la paginación, debemos pasar el límite, el número de página y la cantidad de páginas para saltar al componente que representaría la lista. Estamos logrando esto usando la propiedad de contexto del objeto de configuración createPage . Accederemos a estas propiedades desde la página para realizar otra consulta de graphql para obtener publicaciones dentro del límite.

También podemos notar que usamos el mismo componente de plantilla para la lista, y solo la ruta cambia utilizando el índice de la matriz de fragmentos que habíamos definido anteriormente. Gatsby pasará los datos necesarios para una URL determinada que coincida con /{chunkIndex} , por lo que podemos tener / para las primeras diez publicaciones y /2 para las próximas diez publicaciones.

Página de inicio del blog moderno
Página de inicio del blog moderno (vista previa grande)

Listado de publicaciones de representación

El componente que representa estas páginas se puede encontrar en src/templates/singlePost/index.js de la carpeta del proyecto. También exporta un ayudante de graphql que extrae el límite y el parámetro de consulta de página que recibió del proceso createPages para consultar a gatsby por publicaciones dentro del rango de la página actual.

 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 página de publicación

Para ver el contenido de una página, necesitamos crear la página mediante programación dentro del archivo API gatsby-node.js . Primero, tenemos que definir un nuevo componente para representar el contenido, para esto, tenemos 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 } } } `;

Nuevamente, estamos usando un asistente de graphQL para extraer una página mediante una consulta de slug que se enviaría a la página a través de la API createPages.

A continuación, debemos agregar el siguiente código a gatsby-node.js al final de la función 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, }, }); });

Y podríamos visitar '/{pageSlug}' y hacer que represente el contenido del archivo de descuento para esa página como HTML. Como ejemplo, https://localhost:8000/the-butterfly-of-the-edge debería cargar el HTML convertido para el descuento en: content/2020_05/01.md , similar a todos los slug válidos. ¡Genial!

Página de publicación de blog moderna
Página de publicación de blog moderna (vista previa grande)

Categorías y etiquetas de representación

El componente de plantilla de publicación única tiene un enlace a una página en el formato /categories/{categoryName} para enumerar publicaciones con categorías similares.

Primero podemos capturar todas las categorías y etiquetas a medida que construimos la página de publicación única en el archivo gatsby-node.js , luego crear páginas para cada categoría/etiqueta capturada pasando el nombre de categoría/etiqueta.

Una modificación a la sección para crear una sola página de publicación en gatsby-node.js se ve así:

 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, }, }); });

Y dentro del componente para enumerar publicaciones por etiquetas, podemos tener la consulta de exportación pageQuery graphql para publicaciones, incluida esa etiqueta en su lista de etiquetas. Usaremos la función de filter de graphql y el operador $in para lograr esto:

 // 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 } } } } } `;

Y tenemos el mismo proceso en el componente de listado de categorías, y la diferencia es que solo necesitamos encontrar dónde coinciden exactamente las categorías con lo que le pasamos.

 // 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 } } } } } `;

Notable, dentro de los componentes de etiquetas y categorías, representamos enlaces a la página de publicación única para una lectura adicional del contenido de una publicación.

Página de publicación única Hello World con etiqueta
Publicación moderna con categoría etiquetada (vista previa grande)

Agregar soporte para autores

Para admitir varios autores, tenemos que hacer algunas modificaciones en el contenido de nuestra publicación e introducir nuevos conceptos.

Cargar archivos JSON

Primero, deberíamos poder almacenar el contenido de los autores en un archivo JSON como este:

 { "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" } ] }

Los estaríamos almacenando en un directorio de autor en la raíz de nuestro proyecto como /authors . Tenga en cuenta que el autor JSON tiene mdField que sería el identificador único del campo de autor que introduciremos en el contenido del blog de rebajas; esto asegura que los autores puedan tener múltiples perfiles.

A continuación, tenemos que actualizar los complementos gatsby-config.js que indican gatsby-source-filesystem que cargue el contenido del directorio author authors/ en el nodo de archivos.

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

Por último, instalaremos gatsby-transform-json para transformar los archivos JSON creados para un manejo sencillo y un procesamiento adecuado.

 npm install gatsby-transformer-json --save

E incluirlo dentro de los complementos de gatsby-config.js ,

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

Página de consulta y creación de autores

Para empezar, debemos consultar a todos los autores en nuestro directorioauthors authors/ dentro de gatsby-config.js que se han cargado en la capa de datos, debemos agregar el código a continuación para createPages la función API de páginas.

 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, }, }); });

En este fragmento, estamos extrayendo a todos los autores del tipo allAuthorsJson, luego llamamos a cada uno de los nodos para crear una página donde pasamos el mdField para distinguir el autor y los authorDetails del autor para obtener información completa sobre el autor.

Representación de las publicaciones del autor

En el componente que representa la página que se puede encontrar en src/templates/authorsListing/index.jsx , tenemos el siguiente contenido para el archivo

 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 } } } } } `;

En el código anterior, exportamos pageQuery como lo hacemos nosotros, para crear una consulta GraphQL para buscar publicaciones que coincidan con un autor, estamos usando el operador $eq para lograr esto, generando enlaces a una sola página de publicación para lectura adicional.

Página de autor del blog moderno
Página del autor del blog moderno (vista previa grande)

Conclusión

En Gatsby, podemos consultar cualquier dato que exista dentro de su capa de acceso a datos con el uso de consultas GraphQL y pasar variables utilizando algunas construcciones definidas por la arquitectura de Gatsby. hemos visto cómo podemos usar el ayudante de graphql en varios lugares y comprender los patrones ampliamente utilizados para consultar datos en los sitios web de Gatsby con la ayuda de GraphQL.

GraphQL es muy poderoso y podría hacer otras cosas como la mutación de datos en un servidor. Gatsby no necesita actualizar sus datos en tiempo de ejecución, por lo que no es compatible con la función de mutación de GraphQL.

GraphQL es una gran tecnología, y Gatsby la hace muy interesante de usar en su marco.

Referencias

  • Compatibilidad con Gatsby para GraphQL
  • Por qué Gatsby usa GraphQL
  • Conceptos de GraphQL en Gatsby
  • Cómo GraphQL: conceptos básicos
  • Lenguaje de definición de esquemas en GraphQL
  • Una introducción a GraphQL
  • Inicio avanzado de Gatsby