Расширенное использование GraphQL на веб-сайтах Gatsby
Опубликовано: 2022-03-10До выпуска GraphQL в 2015 году передача репрезентативного состояния (REST) была основным способом взаимодействия с API. Таким образом, внедрение GraphQL стало серьезным изменением в разработке программного обеспечения.
В качестве современного генератора статических сайтов Gatsby использует GraphQL, чтобы предоставить краткую методологию для ввода данных и управления ими в инфраструктуре. В этой статье мы более подробно рассмотрим GraphQL и то, как мы можем интегрировать его в веб-сайт Gatsby, создав и внедрив расширенный поиск и преобразование данных в Gatsby. Результатом стал блог издателя, который может использоваться любой издательской фирмой для обмена контентом своих авторов.
Что такое GraphQL?
Судя по названию QL , GraphQL представляет собой язык запросов в сочетании с набором инструментов, созданных для обеспечения гибкости и эффективности способов извлечения данных из источника. С GraphQL клиент/потребитель может запросить именно те данные, которые ему нужны. Сервер/поставщик отвечает сигнатурой ответа JSON, соответствующей требованиям, указанным в запросе. Это позволяет нам выражать наши потребности в данных декларативно.
Зачем использовать GraphQL?
Как генератор статических сайтов, Gatsby хранит статические файлы, что делает запрос данных практически невозможным. Часто есть компоненты страницы, которые должны быть динамическими, как отдельная страница сообщения в блоге, поэтому возникает необходимость извлекать данные из источника и преобразовывать их в необходимый формат, точно так же, как сообщения в блоге хранятся в файлах уценки. Некоторые плагины предоставляют данные из различных источников, что оставляет вам возможность запрашивать и преобразовывать необходимые данные из источника.
Согласно списку на gatsby.org, GraphQL полезен в Gatsby для:
- Устранить шаблон
- Вставьте сложности внешнего интерфейса в запросы
- Обеспечьте идеальное решение для всегда сложных данных современного приложения.
- Наконец, чтобы убрать раздувание кода, тем самым повысив производительность.
Концепции GraphQL
Гэтсби придерживается тех же самых широко используемых идей GraphQL; некоторые из этих понятий:
Язык определения схемы
GraphQL SDL — это система типов, встроенная в GraphQL, и вы можете использовать ее для создания новых типов данных.
Мы можем объявить тип для страны, и его атрибуты могут включать название, континент, население, ВВП и количество штатов.
В качестве примера ниже мы создали новый тип с именем Aleem . У него есть hobbies
, которые представляют собой массив строк и не обязательны, но страна, семейное положение и должности необходимы из-за ! они включают в себя также сообщения, ссылающиеся на другой тип, сообщение .
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 }
Запросы
Мы можем использовать запросы для извлечения данных из источника GraphQL.
Учитывая набор данных, как показано ниже
{ 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", }, ], }, ], }, };
У нас может быть запрос для получения страны и сообщений из данных:
query { authors { country, posts { title } } }
Ответ, который мы получим, должен содержать JSON-данные постов блога, только заголовок и ничего больше:
[ { country: “Nigeria”, posts: [{...}, {...}, {...}] }, { country: “Tunisia”, posts: [] }, { title: “Ghana”, posts: []}, ]
Мы также можем использовать аргументы в качестве условий для запроса:
query { authors (country: “Nigeria”) { country, posts { title } } }
Который должен вернуться
[ { country: “Nigeria”, posts: [{...}, {...}, {...}] } ]
Вложенные поля также могут быть запрошены, как сообщения с типом сообщения, вы можете запросить только заголовки:
query { authors(country: 'Nigeria') { country, posts { title } } }
И он должен возвращать любой тип автора, соответствующий Нигерии , возвращающий страну и массив сообщений, содержащий объекты только с полем заголовка.
Гэтсби с GraphQL
Чтобы избежать накладных расходов, связанных с наличием сервера/службы, обслуживающей данные, которые может преобразовать GraphQL, Gatsby выполняет запросы GraphQL во время сборки. Данные передаются компонентам в процессе сборки, что делает их легко доступными внутри браузера без сервера.
Тем не менее, Gatsby может работать как сервер, к которому могут обращаться другие клиенты GraphQL, такие как GraphiQL, в браузере.
Gatsby Способы взаимодействия с GraphQL
Есть два места, где Gatsby может взаимодействовать с GraphQL: через файл API gatsby-node.js и через компоненты страницы.
gatsby-node.js
API createPage можно настроить как функцию, которая будет получать хелпер graphql
как часть элементов в первом аргументе, переданном функции.
// 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 } } } } }`) }
В приведенном выше коде мы использовали помощник GraphQL для извлечения файлов уценки из уровня данных Gatsby. И мы можем внедрить это, чтобы создать страницу и изменить существующие данные внутри слоя данных Gatsby.
Компоненты страницы
Компоненты страницы внутри каталога /pages или шаблоны, отображаемые действием API createPage
, могут импортировать graphql
из модуля gatsby
и экспортировать pageQuery
. В свою очередь, Гэтсби вводил новые data
реквизита в реквизиты компонента страницы, содержащего разрешенные данные.
import React from "react"; import { graphql } from "gatsby"; const Page = props => { return
{JSON.stringify(реквизиты.данные)}; }; экспортировать const pageQuery = graphql` запрос { ... } `; экспорт страницы по умолчанию;
В других компонентах
Другие компоненты могут импортировать компоненты graphql
и StaticQuery
из модуля gatsby
, отображать реквизиты запроса <StaticQuery/>
, которые реализуют помощник Graphql, и отображать для получения возвращенных данных.
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;
Создание современного и продвинутого блога Gatsby Publishing
В этом разделе мы рассмотрим процесс создания блога, который поддерживает теги, категоризацию, разбивку на страницы и группировку статей по авторам. Мы будем использовать плагины экосистемы Гэтсби, чтобы добавить некоторые функции и использовать логику в запросах GraphQL, чтобы создать блог издателя, готовый для публикаций нескольких авторов.
Окончательную версию блога, который мы создадим, можно найти здесь, также код размещен на Github.
Инициализация проекта
Как и на любом веб-сайте Gatsby, мы инициализируем его из стартера, здесь мы будем использовать расширенный стартер, но модифицированный, чтобы соответствовать нашему варианту использования.
Сначала клонируйте этот репозиторий Github, измените рабочую ветку на dev-init, а затем запустите npm run develop
из папки проекта, чтобы запустить сервер разработки, сделав сайт доступным по адресу https://localhost:8000.
git clone git@github.com:limistah/modern-gatsby-starter.git cd modern-gatsby-starter git checkout dev-init npm install npm run develop
Посещение https://localhost:8000 покажет домашнюю страницу по умолчанию для этой ветки.
Создание контента для сообщений в блоге
Доступ к некоторому контенту сообщений, включенному в репозиторий проекта, можно получить в ветке dev-blog-content. Организация каталога контента выглядит следующим образом /content/YYYY_MM/DD.md
, в котором посты группируются по созданному месяцу года.
Содержимое поста в блоге имеет title
, date
, author
, 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 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.
Отображение содержимого поста
Прежде чем мы сможем отображать наши записи Markdown в HTML, нам нужно выполнить некоторую обработку. Во-первых, загрузка файлов в хранилище Gatsby, преобразование MD в HTML, связывание зависимостей изображений и тому подобное. Чтобы облегчить это, мы будем использовать множество плагинов экосистемы Gatsby.
Мы можем использовать эти плагины, обновив gatsby-config.js в корне проекта, чтобы он выглядел следующим образом:
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", ], }, }, ], };
Мы поручили gatsby включить плагины, которые помогут нам в выполнении некоторых действий, в частности, извлекать файлы из папки /static для статических файлов и /content для наших сообщений в блоге. Кроме того, мы включили плагин преобразования примечаний для преобразования всех файлов, оканчивающихся на .md или .markdown, в узел со всеми полями примечания для рендеринга уценки в виде HTML.
Наконец, мы включили плагины для работы с узлами, сгенерированными gatsby-transformer-remark
.
Реализация API-файла gatsby-config.js
Двигаясь вперед, внутри gatsby-node.js в корне проекта мы можем экспортировать функцию с именем createPage
и иметь содержимое функции, чтобы использовать помощник graphQL для извлечения узлов из уровня содержимого GatsbyJS.
Первое обновление этой страницы будет включать установку слагов на узлах примечаний MarkDown. Мы прослушаем API onCreateNode и создадим узел, чтобы определить, является ли он типом MarkdownRemark, прежде чем мы обновим узел, чтобы включить слаг и дату соответственно.
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 }); } };
Список сообщений
На этом этапе мы можем реализовать API createPages
для запроса всех уценок и создать страницу с путем в виде слага, который мы создали выше. Смотрите на 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, }); } };
В функции createPages
мы используем помощник graphql
, предоставленный Gatsby, для запроса данных из уровня контента. Для этого мы использовали стандартный запрос Graphql и передали запрос для получения контента из типа allMarkdownRemark
. Затем перешел к сортировке сообщений по дате создания.

Затем мы извлекли свойство postPerPage
из импортированного объекта конфигурации, которое используется для сокращения общего количества сообщений до указанного количества сообщений для одной страницы.
Чтобы создать страницу со списком, которая поддерживает нумерацию страниц, нам нужно передать лимит, pageNumber и количество страниц для пропуска компоненту, который будет отображать список. Мы достигаем этого, используя свойство контекста объекта конфигурации createPage
. Мы будем получать доступ к этим свойствам со страницы, чтобы сделать еще один запрос graphql для получения сообщений в пределах лимита.
Мы также можем заметить, что мы используем тот же компонент шаблона для листинга, и меняется только путь с использованием индекса массива фрагментов, который мы определили ранее. Гэтсби передаст необходимые данные для данного URL-адреса, соответствующего /{chunkIndex}
, поэтому мы можем иметь /
для первых десяти сообщений и /2
для следующих десяти сообщений.

Рендеринг пост-листинга
Компонент, отображающий эти страницы, можно найти в src/templates/singlePost/index.js
папки проекта. Он также экспортирует хелпер graphql
, который извлекает параметр запроса limit и page, полученный от процесса createPages, для запроса gatsby сообщений в диапазоне текущей страницы.
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 } } } } } `;
Страница сообщения
Чтобы просмотреть содержимое страницы, нам нужно программно создать страницу в gatsby-node.js
API. Во-первых, мы должны определить новый компонент для рендеринга контента, для этого у нас есть 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 } } } `;
Опять же, мы используем помощник graphQL для извлечения страницы с помощью слаг-запроса, который будет отправлен на страницу через API createPages.
Затем мы должны добавить приведенный ниже код в gatsby-node.js в конце функции 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, }, }); });
И мы могли бы посетить '/{pageSlug}' и заставить его отображать содержимое файла уценки для этой страницы в виде HTML. Например, https://localhost:8000/the-butterfly-of-the-edge должен загружать преобразованный HTML для уценки по адресу: content/2020_05/01.md
, аналогично всем допустимым слагам. Здорово!

Отображение категорий и тегов
Компонент шаблона одиночного поста имеет ссылку на страницу в формате /categories/{categoryName}
, чтобы перечислить посты с похожими категориями.
Сначала мы можем перехватить все категории и теги, создав единую страницу публикации в файле gatsby-node.js
, а затем создать страницы для каждой перехваченной категории/тега, передавая имя категории/тега.
Модификация раздела для создания отдельной страницы поста в gatsby-node.js выглядит так:
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, }, }); });
А внутри компонента для вывода сообщений по тегам мы можем иметь граф запроса экспорта pageQuery
для сообщений, включая этот тег в свой список тегов. Для этого мы будем использовать функцию filter
graphql и оператор $in:
// 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 } } } } } `;
И у нас есть тот же процесс в компоненте списка категорий, и разница в том, что нам нужно только найти, где категории точно совпадают с тем, что мы ему передаем.
// 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 } } } } } `;
Примечательно, что внутри обоих компонентов тегов и категорий мы отображаем ссылки на отдельную страницу публикации для дальнейшего чтения содержимого публикации.

Добавление поддержки для авторов
Чтобы поддерживать несколько авторов, мы должны внести некоторые изменения в содержание наших сообщений и ввести новые концепции.
Загрузить файлы JSON
Во-первых, мы должны иметь возможность хранить содержимое авторов в файле JSON следующим образом:
{ "mdField": "aleem", "name": "Aleem Isiaka", "email": "aleem.isiaka@gmail.com", "location": "Lagos, Nigeria", "avatar": "https://api.adorable.io/avatars/55/abott@adorable.png", "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:aleem.isiaka@gmail.com", "iconClassName": "fa fa-envelope" } ] }
Мы будем хранить их в каталоге автора в корне нашего проекта как /authors
. Обратите внимание, что у автора JSON есть mdField
, который будет уникальным идентификатором поля автора, которое мы будем вводить в контент блога уценки; это гарантирует, что у авторов может быть несколько профилей.
Затем мы должны обновить gatsby-config.js
предписывая gatsby-source-filesystem
загружать содержимое из каталога author authors/
в узел Files.
// gatsby-config.js { resolve: `gatsby-source-filesystem`, options: { name: "authors", path: `${__dirname}/authors/`, }, }
Наконец, мы установим gatsby-transform-json
для преобразования файлов JSON, созданных для удобства обработки и правильной обработки.
npm install gatsby-transformer-json --save
И включите его в плагины gatsby-config.js
,
module.exports = { plugins: [ // ...other plugins `gatsby-transformer-json` ], };
Запрос и создание страницы авторов
Для начала нам нужно запросить всех авторов в нашем каталоге author authors/
внутри gatsby-config.js
, которые были загружены на уровень данных, мы должны добавить приведенный ниже код к функции API createPages
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, }, }); });
В этом фрагменте мы извлекаем всех авторов из типа allAuthorsJson, а затем вызываем forEach на узлах для создания страницы, на которой мы передаем mdField
, чтобы различать автора и authorDetails
для получения полной информации об авторе.
Рендеринг авторских постов
В компоненте, отображающем страницу, которую можно найти по адресу src/templates/authorsListing/index.jsx
, у нас есть приведенный ниже контент для файла.
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 } } } } } `;
В приведенном выше коде мы экспортировали pageQuery
, как мы это делаем, чтобы создать запрос GraphQL для получения сообщений, соответствующих автору, мы используем оператор $eq
, чтобы добиться этого, генерируя ссылки на одну страницу сообщения для дальнейшего чтения.

Заключение
В Gatsby мы можем запрашивать любые данные, которые существуют внутри его уровня доступа к данным, с использованием запроса GraphQL и передавать переменные, используя некоторые конструкции, определенные архитектурой Gatsby. мы увидели, как можно использовать помощника graphql
в разных местах, и поняли широко используемые шаблоны для запросов данных на веб-сайтах Гэтсби с помощью GraphQL.
GraphQL очень мощный и может делать другие вещи, такие как изменение данных на сервере. Gatsby не нужно обновлять свои данные во время выполнения, поэтому он не поддерживает функцию мутации GraphQL.
GraphQL — отличная технология, и Gatsby делает ее очень интересной для использования в своей структуре.
использованная литература
- Поддержка Gatsby для GraphQL
- Почему Гэтсби использует GraphQL
- Концепции GraphQL в Gatsby
- Как использовать GraphQL: основные понятия
- Язык определения схемы в GraphQL
- Введение в GraphQL
- Гэтсби Продвинутый Стартер