Gatsby Web Sitelerinde Gelişmiş GraphQL Kullanımı
Yayınlanan: 2022-03-102015 yılında GraphQL'nin piyasaya sürülmesinden önce, Temsili Durum Transferi (REST), bir API ile arayüz oluşturmanın ana yoluydu. GraphQL'nin tanıtılması bu nedenle yazılım geliştirmede büyük bir değişiklikti.
Modern bir statik site oluşturucu olarak Gatsby, verileri çerçeveye getirmek ve işlemek için özlü bir metodoloji sağlamak için GraphQL'den yararlanır. Bu makalede, GraphQL'ye ve Gatsby'de gelişmiş veri kaynağı ve dönüşümü oluşturarak ve uygulayarak onu bir Gatsby web sitesine nasıl entegre edebileceğimize daha yakından bakacağız. Sonuç, herhangi bir yayıncılık firması tarafından yazarlarının içeriğini paylaşmak için kullanılabilecek bir yayıncının blogudur.
GraphQL Nedir?
Adında QL olan GraphQL, bir kaynaktan veri çekme şeklimizde esneklik ve verimlilik sağlamak için oluşturulmuş bir dizi araçla birleştirilmiş bir sorgu dilidir . GraphQL ile bir müşteri/tüketici tam olarak ihtiyaç duyduğu verileri talep edebilir. Sunucu/sağlayıcı, sorguda belirtilen gereksinimlerle eşleşen bir JSON yanıt imzasıyla yanıt verir. Veri ihtiyaçlarımızı bildirimsel olarak ifade etmemizi sağlar.
Neden GraphQL Kullanılır?
Statik bir site oluşturucu olarak Gatsby, statik dosyaları depolar, bu da verileri sorgulamayı neredeyse imkansız hale getirir. Genellikle tek bir blog gönderi sayfası gibi dinamik olması gereken sayfa bileşenleri vardır, bu nedenle, tıpkı blog gönderilerinin markdown dosyalarında saklanması gibi, bir kaynaktan veri çekme ve gerekli biçime dönüştürme ihtiyacı ortaya çıkacaktır. Bazı eklentiler, çeşitli kaynaklardan veri sağlar, bu da sizi bir kaynaktan gerekli verileri sorgulama ve dönüştürme ile bırakır.
Gatsby.org'daki bir listeye göre GraphQL, Gatsby'de aşağıdakiler için yararlıdır:
- Kazan plakasını ortadan kaldırın
- Ön uç karmaşıklıklarını sorgulara aktarın
- Modern bir uygulamanın her zaman karmaşık verileri için mükemmel bir çözüm sağlayın
- Son olarak, kod şişkinliğini kaldırmak, böylece performansı artırmak.
GraphQL Kavramları
Gatsby, yaygın olarak kullanılan GraphQL fikirlerinin aynısını sürdürmektedir; bu kavramlardan bazıları şunlardır:
Şema Tanımlama Dili
GraphQL SDL, GraphQL'e dahil edilmiş bir tür sistemidir ve bunu verileriniz için yeni türler oluşturmak için kullanabilirsiniz.
Bir ülke için bir tür ilan edebiliriz ve nitelikleri bir isim, kıta, nüfus, gdp ve eyalet sayısını içerebilir.
Aşağıdaki örnek olarak Aleem ismiyle yeni bir tür oluşturduk. Bir dizi diziden oluşan ve zorunlu olmayan hobbies
vardır, ancak ülke, medeni durum ve gönderiler nedeniyle ! içerirler, ayrıca gönderiler başka bir türe referans verir, 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 }
Sorguları
Bir GraphQL kaynağından veri çekmek için Sorguları kullanabiliriz.
Aşağıdaki gibi bir veri seti göz önüne alındığında
{ 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", }, ], }, ], }, };
Ülkeyi ve verilerden gönderileri almak için bir sorgumuz olabilir:
query { authors { country, posts { title } } }
Alacağımız yanıt, yalnızca başlık ve başka bir şey olmayan blog gönderilerinin JSON verilerini içermelidir:
[ { country: “Nigeria”, posts: [{...}, {...}, {...}] }, { country: “Tunisia”, posts: [] }, { title: “Ghana”, posts: []}, ]
Argümanları bir sorgu için koşul olarak da kullanabiliriz:
query { authors (country: “Nigeria”) { country, posts { title } } }
Hangisi geri dönmeli
[ { country: “Nigeria”, posts: [{...}, {...}, {...}] } ]
İç içe alanlar da sorgulanabilir, Post tipindeki gönderiler gibi, sadece başlıkları isteyebilirsiniz:
query { authors(country: 'Nigeria') { country, posts { title } } }
Ve Nijerya ile eşleşen herhangi bir Yazar türünü döndürerek ülkeyi döndürmelidir ve yalnızca başlık alanına sahip nesneleri içeren diziyi göndermelidir.
GraphQL ile Gatsby
Gatsby, GraphQL'nin dönüştürebileceği verileri sunan bir sunucuya/hizmete sahip olmanın ek yükünü önlemek için, derleme zamanında GraphQL sorgularını yürütür. Veriler, oluşturma işlemi sırasında bileşenlere sağlanır, bu da onları bir sunucu olmadan tarayıcının içinde hazır hale getirir.
Yine de Gatsby, bir tarayıcıda GraphiQL gibi diğer GraphQL istemcileri tarafından sorgulanabilen bir sunucu olarak çalışabilir.
Gatsby GraphQL ile Etkileşim Yolları
Gatsby'nin bir gatsby-node.js API dosyası ve sayfa bileşenleri aracılığıyla GraphQL ile etkileşimde bulunabileceği iki yer vardır.
gatsby-node.js
createPage API, işleve iletilen ilk bağımsız değişkendeki öğelerin bir parçası olarak bir graphql
yardımcısı alacak bir işlev olarak yapılandırılabilir.
// 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 } } } } }`) }
Yukarıdaki kodda, Gatsby'nin veri katmanından markdown dosyalarını almak için GraphQL yardımcısını kullandık. Ve bunu bir sayfa oluşturmak ve Gatsby veri katmanındaki mevcut verileri değiştirmek için enjekte edebiliriz.
Sayfa Bileşenleri
/pages dizini içindeki sayfa bileşenleri veya createPage
API eylemi tarafından oluşturulan şablonlar, gatsby
graphql
aktarabilir ve bir pageQuery
dışa aktarabilir. Buna karşılık Gatsby, çözümlenen verileri içeren sayfa bileşeninin desteklerine yeni bir destek data
enjekte edecekti.
import React from "react"; import { graphql } from "gatsby"; const Page = props => { return
{JSON.stringify(props.data)}; }; dışa aktarma const pageQuery = graphql` sorgu { ... } `; varsayılan Sayfayı dışa aktar;
Diğer Bileşenlerde
Diğer bileşenler, gatsby
modülünden graphql
ve StaticQuery
bileşenlerini içe aktarabilir, Graphql yardımcısını uygulayan <StaticQuery/>
geçen sorgu desteklerini oluşturabilir ve döndürülen verileri almak için işleyebilir.
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;
Modern ve Gelişmiş Bir Gatsby Yayıncılık Blogu Oluşturma
Bu bölümde, makaleleri yazarlara göre etiketlemeyi, kategorilere ayırmayı, sayfalandırmayı ve gruplandırmayı destekleyen bir blog oluşturma sürecinden geçeceğiz. Bazı özellikleri getirmek için Gatsby ekosisteminin eklentilerini kullanacağız ve bir yayıncının blogunu birden çok yazarlı yayına hazır hale getirmek için GraphQL sorgularında mantık kullanacağız.
Oluşturacağımız blogun son halini burada bulabilirsiniz, ayrıca kod Github'da barındırılmaktadır.
Projeyi Başlatma
Herhangi bir Gatsby web sitesinde olduğu gibi, bir başlangıçtan başlatıyoruz, burada gelişmiş başlatıcıyı kullanacağız, ancak kullanım durumumuzu karşılamak için değiştireceğiz.
Önce bu Github deposunu klonlayın, çalışma dalını dev-init olarak değiştirin ve ardından siteyi https://localhost:8000 adresinde kullanıma sunan geliştirme sunucusunu başlatmak için projenin klasöründen npm run develop
.
git clone [email protected]:limistah/modern-gatsby-starter.git cd modern-gatsby-starter git checkout dev-init npm install npm run develop
https://localhost:8000 adresini ziyaret etmek, bu dal için varsayılan ana sayfayı gösterecektir.
Blog Yazıları İçeriği Oluşturma
Proje havuzunda yer alan bazı gönderi içeriğine dev-blog-content dalında erişilebilir. İçerik dizininin organizasyonu, gönderileri bir yılın oluşturulan ayına göre gruplayan /content/YYYY_MM/DD.md
gibi görünür.
Blog gönderisi içeriği, bir gönderiyi ayırt etmek ve üzerinde biraz daha fazla işlem yapmak için kullanacağımız, onun ön maddesi olarak title
, date
, author
, category
ve tags
sahiptir, içeriğin geri kalanı ise gönderinin gövdesidir.
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.
Gönderi İçeriğini Görüntüleme
Markdown gönderilerimizi HTML olarak oluşturmadan önce, bazı işlemler yapmalıyız. İlk olarak, dosyaları Gatsby deposuna yüklemek, MD'yi HTML'ye ayrıştırmak, görüntü bağımlılıklarını ve beğenileri birbirine bağlamak. Bunu kolaylaştırmak için Gatsby ekosisteminden bir dizi eklenti kullanacağız.
Bu eklentileri, projenin kökündeki gatsby-config.js dosyasını aşağıdaki gibi görünecek şekilde güncelleyerek kullanabiliriz:
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'ye, özellikle statik dosyalar için /static klasöründen dosyaları ve blog gönderilerimiz için /content'i çekmek gibi bazı eylemleri gerçekleştirmemize yardımcı olacak eklentileri dahil etmesi talimatını verdik. Ayrıca, .md veya .markdown ile biten tüm dosyaları, işaretlemeyi HTML olarak oluşturmak için tüm açıklama alanlarını içeren bir düğüme dönüştürmek için bir açıklama dönüştürücü eklentisi ekledik.
Son olarak, gatsby-transformer-remark
tarafından oluşturulan düğümlerde çalışan eklentileri ekledik.
gatsby-config.js
API Dosyasını Uygulama
İleriye doğru, proje kökündeki gatsby-node.js içinde, createPage
adlı bir işlevi dışa aktarabilir ve GatsbyJS'nin içerik katmanından düğümleri çekmek için graphQL yardımcısını kullanmak için işlevin içeriğine sahip olabiliriz.
Bu sayfadaki ilk güncelleme, MarkDown açıklama düğümlerinde bir slug ayarımızın olmasını sağlamayı içerecektir. OnCreateNode API'sini dinleyeceğiz ve düğümü bir bilgi ve tarih içerecek şekilde güncellemeden önce bir MarkdownRemark türü olup olmadığını belirlemek için oluşturulan düğümü alacağız.
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 }); } };
Gönderi Listesi
Bu noktada, tüm markdown'ları sorgulamak için createPages
API'sini uygulayabilir ve yukarıda oluşturduğumuz slug gibi path ile bir sayfa oluşturabiliriz. Github'da görün.
//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
işlevinde, içerik katmanındaki verileri sorgulamak için Gatsby tarafından sağlanan graphql
yardımcısını kullanırız. Bunu yapmak için standart bir Graphql sorgusu kullandık ve allMarkdownRemark
türünden içerik almak için bir sorgu ilettik. Ardından gönderileri oluşturulan tarihe göre sıralamak için ilerledi.
Ardından, toplam gönderileri tek bir sayfa için belirtilen gönderi sayısına indirmek için kullanılan, içe aktarılan bir yapılandırma nesnesinden bir postPerPage
özelliği çektik.
Sayfalandırmayı destekleyen bir liste sayfası oluşturmak için, listeyi oluşturacak bileşene atlanacak sınırı, pageNumber'ı ve sayfa sayısını geçmemiz gerekir. Bunu, createPage
yapılandırma nesnesinin bağlam özelliğini kullanarak gerçekleştiriyoruz. Limit dahilindeki gönderileri almak için başka bir graphql sorgusu yapmak için bu özelliklere sayfadan erişeceğiz.
Ayrıca, listeleme için aynı şablon bileşenini kullandığımızı ve önceden tanımladığımız yığın dizisinin indeksini kullanarak yalnızca yolun değiştiğini fark edebiliriz. Gatsby, /{chunkIndex}
ile eşleşen belirli bir URL için gerekli verileri iletir, böylece ilk on gönderi için /
ve sonraki on gönderi için /2
olabilir.
Gönderi Listesi Oluşturma
Bu sayfaları oluşturan bileşen, proje klasörünün src/templates/singlePost/index.js
. Ayrıca, geçerli sayfanın aralığındaki gönderiler için gatsby'yi sorgulamak için createPages işleminden aldığı limit ve sayfa sorgu parametresini çeken bir graphql
yardımcısını dışa aktarır.
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 } } } } } `;
Gönderi Sayfası
Bir sayfanın içeriğini görüntülemek için, sayfayı programlı olarak gatsby-node.js
API Dosyası içinde oluşturmamız gerekir. İlk olarak, içeriği oluşturmak için yeni bir bileşen tanımlamamız gerekiyor, bunun için src/templates/singlePost/index.jsx
var.
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 } } } `;
Yine, createPages API aracılığıyla sayfaya gönderilecek olan bir bilgi sorgusu ile bir sayfayı çıkarmak için bir graphQL yardımcısı kullanıyoruz.
Ardından, createPages
API işlevinin sonunda gatsby-node.js'ye aşağıdaki kodu eklemeliyiz.
// 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, }, }); });
Ve '/{pageSlug}' adresini ziyaret edebilir ve o sayfa için markdown dosyasının içeriğini HTML olarak oluşturmasını sağlayabiliriz. Örnek olarak, https://localhost:8000/the-butterfly-of-the-edge, işaretleme için dönüştürülmüş HTML'yi tüm geçerli sümüklü böceklere benzer şekilde content/2020_05/01.md
. Harika!
Kategorileri ve Etiketleri Oluşturma
Tek gönderi şablonu bileşeni, benzer kategorilere sahip gönderileri listelemek için /categories/{categoryName}
biçiminde bir sayfaya bağlantı içerir.
gatsby-node.js
dosyasında tek gönderi sayfasını oluştururken önce tüm kategorileri ve etiketleri yakalayabiliriz, ardından yakalanan her kategori/etiket için kategori/etiket adını geçen sayfalar oluşturabiliriz.
gatsby-node.js'de tek gönderi sayfası oluşturma bölümünde yapılan bir değişiklik şöyle görünür:
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, }, }); });
Gönderileri etiketlere göre listelemek için bileşenin içinde, etiketler listesinde bu etiket dahil olmak üzere gönderiler için pageQuery
dışa aktarma sorgusu graphql'ye sahip olabiliriz. Bunu başarmak için graphql'nin filter
işlevini ve $in operatörünü kullanacağız:
// 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 } } } } } `;
Ve kategori listeleme bileşeninde de aynı süreci yaşıyoruz ve fark şu ki, sadece kategorilerin tam olarak ona ilettiklerimizle eşleştiği yeri bulmamız gerekiyor.
// 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 } } } } } `;
Dikkat çekici, hem etiketler hem de kategori bileşenleri içinde, bir gönderinin içeriğini daha fazla okumak için tek bir gönderi sayfasına bağlantılar oluşturuyoruz.
Yazarlar İçin Destek Ekleme
Birden fazla yazarı desteklemek için gönderi içeriğimizde bazı değişiklikler yapmamız ve yeni kavramlar tanıtmamız gerekiyor.
JSON Dosyalarını Yükle
İlk olarak, yazarların içeriğini aşağıdaki gibi bir JSON dosyasında saklayabilmemiz gerekir:
{ "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" } ] }
Bunları projemizin kökündeki bir yazarın dizininde /authors
olarak saklayacağız. Yazar JSON'un, markdown blog içeriğine sunacağımız yazar alanının benzersiz tanımlayıcısı olacak mdField
sahip olduğuna dikkat edin; bu, yazarların birden fazla profile sahip olmasını sağlar.
Ardından, gatsby-source-filesystem
içeriği authors/
dizinden Dosyalar Düğümüne gatsby-config.js
eklentilerini güncellememiz gerekiyor.
// gatsby-config.js { resolve: `gatsby-source-filesystem`, options: { name: "authors", path: `${__dirname}/authors/`, }, }
Son olarak, kolay kullanım ve doğru işleme için oluşturulan JSON dosyalarını dönüştürmek için gatsby-transform-json
yükleyeceğiz.
npm install gatsby-transformer-json --save
Ve onu gatsby-config.js
eklentilerinin içine dahil edin,
module.exports = { plugins: [ // ...other plugins `gatsby-transformer-json` ], };
Yazarlar Sayfası Sorgulama ve Oluşturma
Başlangıç olarak, veri katmanına yüklenen gatsby-config.js
içindeki authors/
dizinimizin içindeki tüm yazarları sorgulamamız gerekiyor, aşağıdaki kodu createPages
API işlevine eklemeliyiz.
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, }, }); });
Bu snippet'te, allAuthorsJson türünden tüm yazarları çekiyoruz, ardından yazar hakkında tam bilgi için authorDetails
ve yazar hakkında tam bilgi için mdField
bir sayfa oluşturmak için düğümlerdeki forEach'i çağırıyoruz.
Yazarın Gönderilerini Oluşturma
src/templates/authorsListing/index.jsx
adresinde bulunabilecek sayfayı oluşturan bileşende, dosya için aşağıdaki içeriğe sahibiz
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 } } } } } `;
Yukarıdaki kodda, bir yazar tarafından eşleşen gönderileri getirmek için bir GraphQL sorgusu oluşturmak için yaptığımız gibi pageQuery
dışa aktardık, bunu başarmak için $eq
operatörünü kullanıyoruz, daha fazla okuma için tek bir gönderi sayfasına bağlantılar oluşturuyoruz.
Çözüm
Gatsby'de, GraphQL sorgusu kullanarak veri erişim katmanının içindeki herhangi bir veriyi sorgulayabilir ve Gatsby mimarisi tarafından tanımlanan bazı yapıları kullanarak değişkenleri dolaşabiliriz. çeşitli yerlerde graphql
yardımcısını nasıl kullanabileceğimizi ve GraphQL yardımıyla Gatsby'nin web sitelerinde veri sorgulamak için yaygın olarak kullanılan kalıpları nasıl anlayabileceğimizi gördük.
GraphQL çok güçlüdür ve bir sunucuda veri mutasyonu gibi başka şeyler yapabilir. Gatsby'nin çalışma zamanında verilerini güncellemesi gerekmez, bu nedenle GraphQL'nin mutasyon özelliğini desteklemez.
GraphQL harika bir teknolojidir ve Gatsby, çerçevelerinde kullanmayı çok ilginç kılmaktadır.
Referanslar
- GraphQL için Gatsby desteği
- Gatsby neden GraphQL kullanıyor?
- Gatsby'deki GraphQL kavramları
- GraphQL Nasıl Yapılır: Temel Kavramlar
- GraphQL'de Şema Tanımlama Dili
- GraphQL'e Giriş
- Gatsby Gelişmiş Başlangıç