Uso avanzado de GraphQL en sitios web de Gatsby

Uso avanzado de GraphQL en sitios web de Gatsby

 

 

 

  • SmashingConf New York 2024
  • Smart Interface Design Patterns, 10h video + UX training

  • Índice
    1. ¿Qué es GraphQL?
    2. ¿Por qué utilizar GraphQL?
    3. Conceptos de GraphQL
      1. Lenguaje de definición de esquema
      2. Consultas
      3. Formas de Gatsby de interactuar con GraphQL
    4. Creación de un blog editorial de Gatsby moderno y avanzado
      1. Inicializando el proyecto
      2. Crear contenido de publicaciones de blog
    5. Mostrar contenido de la publicación
      1. Implementación del gatsby-config.jsarchivo API
      2. El listado de publicaciones
      3. Listado de publicaciones de renderizado
    6. La página de publicación
    7. Adding Support For Authors
      1. Load JSON Files

    En este artículo, Aleem Isiaka explica qué son las construcciones de consulta GraphQL y cómo se pueden utilizar 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 avanzado de GraphQL dentro de un sitio web de Gatsby utilizando 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 tanto, la introducción de GraphQL supuso un cambio importante en el desarrollo de software.

    Como generador de sitios estáticos moderno, 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 abastecimiento y transformación de datos avanzados en Gatsby. El resultado es un blog de editor que cualquier editorial podría utilizar para compartir contenidos de sus autores.

    ¿Qué es GraphQL?

    Con el nombre QL en su nombre, GraphQL es un lenguaje de consulta combinado con un conjunto de herramientas creadas para brindar 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é utilizar 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 una sola publicación de blog, 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 de gatsby.org, GraphQL es útil en Gatsby para:

    • Eliminar el texto repetitivo
    • Incorpore las complejidades del frontend a las consultas
    • Proporcionar una solución perfecta para los datos siempre complejos de una aplicación moderna.
    • Finalmente, para eliminar el exceso de código, mejorando así el rendimiento .

    Conceptos de GraphQL

    Gatsby mantiene las mismas ideas de GraphQL que se utilizan ampliamente; algunos de estos conceptos son:

    Lenguaje de definición de esquema

    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 hobbiesuna serie de cadenas que no son obligatorias, pero el país, el estado civil y las publicaciones sí son necesarios debido a ! Incluyen, también publicaciones, referencias de otro 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}

    Consultas

    Podemos usar consultas para extraer datos de una fuente 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 recuperar el país y las publicaciones a partir de los datos:

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

    La respuesta que obtendremos deberá 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 debería regresar

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

    Los campos anidados también se pueden consultar, como las publicaciones con el tipo de publicación, puedes 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 contenga objetos con solo el campo de título.

    Gatsby con GraphQL

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

    Aún así, Gatsby puede ejecutarse como un servidor que otros clientes GraphQL, como GraphiQL , pueden consultar en un navegador.

    Formas de 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 graphqlasistente como parte de los elementos del primer argumento pasado a la función.

    // gatsby-node.js source: https://www.gatsbyjs.org/docs/node-apis/#createPagesexports.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 asistente GraphQL para recuperar archivos de rebajas 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 createPageacción API se pueden importar graphqldesde el gatsbymódulo y exportar un archivo pageQuery. A su vez, Gatsby inyectaría un nuevo accesorio dataen 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(props.data)};};export const pageQuery = graphql` query { ... }`;export default Page;

    En otros componentes

    Otros componentes pueden importar graphqlcomponentes StaticQuerydel gatsbymódulo, representar los lt;StaticQuery/accesorios de consulta que implementan el asistente 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 editorial de Gatsby moderno y avanzado

    En esta sección, recorreremos el proceso de creación de un blog que admita etiquetado, categorización, paginación y agrupación de artículos por autores. Usaremos complementos del ecosistema de Gatsby para incorporar algunas funciones y usaremos lógicas en consultas GraphQL para crear un blog de editor que esté listo para publicaciones de múltiples autores.

    La versión final del blog que crearemos se puede encontrar aquí . Además, el código está alojado en Github .

    Inicializando 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 ejecútelo npm run developdesde 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-startergit checkout dev-initnpm installnpm run develop

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

     

    Crear contenido de publicaciones de blog

    Se puede acceder a algunas publicaciones incluidas 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 del año creado.

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

    title: "Bold Mage"date: "2020-07-12"author: "Tunde Isiaka"category: "tech"tags: - programming - stuff - Ice cream - other---# Donut I love macaroon chocolate barOat 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 soufflé biscuit pie macaroon chocolate cake. Marzipan lemon drops chupa chups sweet cookie sesame snaps jelly halvah.

    Mostrar contenido de la publicación

    Antes de que podamos representar nuestras publicaciones de Markdown en HTML, tenemos que realizar algún procesamiento. Primero, cargar los archivos en el almacenamiento de Gatsby, analizar el MD en HTML, vincular dependencias de imágenes y 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", ], }, }, ],};

    Le hemos indicado a gatsby que incluya complementos para ayudarnos 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 de 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 Markdown como HTML.

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

    Implementación del gatsby-config.jsarchivo API

    En el futuro, dentro de gatsby-node.js en la raíz del proyecto, podemos exportar una función nombrada createPagey tener el contenido de la función para usar el asistente 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 slug configurado 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 una fecha en consecuencia.

    const path = require("path");const _ = require("lodash");const moment = require("moment");const config = require("./config");// Called each time a new node is createdexports.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 // e.g 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 // e.g 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 createPagesAPI para consultar todas las rebajas y crear una página con la ruta como el slug que hemos creado anteriormente. Véalo en Github . Noticias sobre futbol y del Cadiz

    //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 createPagesfunción, utilizamos el graphqlasistente 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 allMarkdownRemarktipo. Luego avanzó para ordenar las publicaciones por fecha de creación.

     

    Luego extrajimos una postPerPagepropiedad de un objeto de configuración importado, que se utiliza para dividir el total de publicaciones en la cantidad especificada de publicaciones para una sola página.

    Para crear una página de listado que admita la paginación, debemos pasar el límite, el número de página y el número de páginas para saltar al componente que representaría la lista. Estamos logrando esto usando la propiedad de contexto del createPageobjeto de configuración. Accederemos a estas propiedades desde la página para realizar otra consulta Graphql para recuperar 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 coincidencia de URL determinada /{chunkIndex}, de modo que podamos tenerlos /para las primeras diez publicaciones y /2para las diez siguientes.

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

    Listado de publicaciones de renderizado

    El componente que representa estas páginas se puede encontrar en src/templates/singlePost/index.jsla carpeta del proyecto. También exporta un graphqlasistente que extrae el límite y el parámetro de consulta de página que recibió del proceso createPages para consultar a Gatsby en busca de 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 gatsby-node.jsarchivo API. Primero, tenemos que definir un nuevo componente para renderizar 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 slug que se enviaría a la página a través de la API createPages.

     

    A continuación, deberíamos agregar el siguiente código a gatsby-node.js al final de la createPagesfunción API.

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

    And we could visit ‘/{pageSlug}’ and have it render the content of the markdown file for that page as HTML. As an example, https://localhost:8000/the-butterfly-of-the-edge should load the converted HTML for the markdown at: content/2020_05/01.md, similar to all valid slugs. Great!

    Modern blog post page (Large preview)

    Rendering Categories And Tags

    The single post template component has a link to a page in the format /categories/{categoryName} to list posts with similar categories.

    We can first catch all the categories and tags as we build the single post page in the gatsby-node.js file, then create pages for each caught category/tag passing the category/tag name.

    A modification to the section for creating single post page in the gatsby-node.js looks like this:

    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 categoriesconst tagsListingPage = path.resolve("./src/templates/tagsListing/index.jsx");// Loops through all the post nodespostsEdges.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, }, });});

    And inside the component for listing posts by tags, we can have the pageQuery export query graphql for posts, including that tag in its tags list. We will use the filter function of graphql and the $in operator to achieve this:

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

    And we have the same process in the categories listing component, and the difference is that we only need to find where the categories match precisely with what we pass to it.

     

    // src/templates/categoriesListing/index.jsximport 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" divPosts 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 } } } } }`;

    Noticeable, inside both of the tags and categories components, we render links to the single post page for further reading of a post’s content.

    Modern post with category tagged (Large preview)

    Adding Support For Authors

    To support multiple authors, we have to make some modifications to our post content and introduce new concepts.

    Load JSON Files

    First, we should be able to store the content of authors in a JSON file like this:

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

    We would be storing them in an author’s directory in the root of our project as /authors. Notice that the author JSON has mdField that would be the unique identifier to the author field we will be introducing to the markdown blog content; this ensures that authors can have multiple profiles.

    Next, we have to update gatsby-config.js plugins instructing gatsby-source-filesystem to load the content from the authors/






    Tal vez te puede interesar:

    1. ¿Deberían abrirse los enlaces en ventanas nuevas?
    2. 24 excelentes tutoriales de AJAX
    3. 70 técnicas nuevas y útiles de AJAX y JavaScript
    4. Más de 45 excelentes recursos y repositorios de fragmentos de código

    Uso avanzado de GraphQL en sitios web de Gatsby

    Uso avanzado de GraphQL en sitios web de Gatsby

    ¿Qué es GraphQL?¿Por qué utilizar GraphQL?Conceptos de GraphQLCreación de un blog editorial de Gatsby moderno y avanzadoMostrar contenido de la publicaci�

    programar

    es

    https://aprendeprogramando.es/static/images/programar-uso-avanzado-de-graphql-en-sitios-web-de-gatsby-1060-0.jpg

    2024-12-03

     

    Uso avanzado de GraphQL en sitios web de Gatsby
    Uso avanzado de GraphQL en sitios web de Gatsby

    Si crees que alguno de los contenidos (texto, imagenes o multimedia) en esta página infringe tus derechos relativos a propiedad intelectual, marcas registradas o cualquier otro de tus derechos, por favor ponte en contacto con nosotros en el mail [email protected] y retiraremos este contenido inmediatamente

     

     

    Update cookies preferences