Penggunaan GraphQL Tingkat Lanjut Di Situs Web Gatsby

Diterbitkan: 2022-03-10
Ringkasan cepat Dalam artikel ini, Aleem Isiaka menjelaskan apa itu konstruksi kueri GraphQL, dan bagaimana konstruksi tersebut dapat digunakan untuk berinteraksi dengan lapisan akses data situs web Gatsby. Mari kita lihat beberapa kasus penggunaan lanjutan GraphQL dalam situs web Gatsby dengan menggunakan data yang cocok dari berbagai sumber.

Sebelum rilis GraphQL pada tahun 2015, Representational State Transfer (REST) ​​adalah cara utama untuk berinteraksi dengan API. Pengenalan GraphQL karena itu merupakan perubahan besar dalam pengembangan perangkat lunak.

Sebagai generator situs statis modern, Gatsby memanfaatkan GraphQL untuk menyediakan metodologi ringkas untuk memasukkan dan memanipulasi data ke dalam kerangka kerja. Pada artikel ini, kita akan melihat lebih dekat GraphQL dan bagaimana kita dapat mengintegrasikannya ke dalam situs web Gatsby dengan membangun dan menerapkan sumber dan transformasi data tingkat lanjut di Gatsby. Hasilnya adalah blog penerbit yang dapat digunakan oleh perusahaan penerbitan mana pun untuk membagikan konten penulisnya.

Apa itu GraphQL?

Mengikuti QL dalam namanya, GraphQL adalah bahasa kueri yang dikombinasikan dengan seperangkat alat yang dibuat untuk memberikan fleksibilitas dan efisiensi dalam cara kami menarik data dari sumber. Dengan GraphQL, klien/konsumen dapat meminta dengan tepat data yang dibutuhkannya. Server/penyedia merespons dengan tanda tangan respons JSON yang cocok dengan persyaratan yang ditentukan dalam kueri. Ini memungkinkan kami untuk mengekspresikan kebutuhan data kami secara deklaratif.

Mengapa Menggunakan GraphQL?

Sebagai generator situs statis, Gatsby menyimpan file statis, yang membuat kueri data hampir tidak mungkin. Seringkali ada komponen halaman yang harus dinamis seperti halaman posting blog tunggal, sehingga kebutuhan untuk menarik data dari sumber dan mengubahnya ke format yang diperlukan akan muncul, seperti posting blog yang disimpan dalam file penurunan harga. Beberapa plugin menyediakan data dari berbagai sumber, yang membuat Anda menanyakan dan mengubah data yang diperlukan dari suatu sumber.

Menurut daftar di gatsby.org, GraphQL berguna di Gatsby untuk:

  • Hilangkan boilerplate
  • Dorong kerumitan frontend ke dalam kueri
  • Memberikan solusi sempurna untuk data yang selalu kompleks dari aplikasi modern
  • Akhirnya, untuk menghapus kode mengasapi, sehingga meningkatkan kinerja.

Konsep GraphQL

Gatsby mempertahankan ide GraphQL yang sama seperti yang banyak digunakan; beberapa konsep tersebut adalah:

Bahasa Definisi Skema

GraphQL SDL adalah sistem tipe yang dimasukkan ke dalam GraphQL, dan Anda dapat menggunakannya untuk membuat tipe baru untuk data Anda.

Kami dapat mendeklarasikan tipe untuk suatu negara, dan atributnya dapat mencakup nama, benua, populasi, gdp, dan jumlah negara bagian.

Seperti contoh di bawah ini, kami telah membuat tipe baru dengan nama Aleem . Ini memiliki hobbies yang merupakan rangkaian string dan tidak diperlukan, tetapi negara, status perkawinan, dan pos diperlukan karena ! mereka termasuk, juga posting referensi jenis lain, Posting .

 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 }

Pertanyaan

Kita dapat menggunakan Query untuk menarik data dari sumber GraphQL.

Mempertimbangkan kumpulan data seperti di bawah ini

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

Kami dapat memiliki kueri untuk mengambil negara dan pos dari data:

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

Respons yang akan kita dapatkan harus berisi data JSON dari posting blog hanya dengan judul dan tidak lebih:

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

Kami juga dapat menggunakan argumen sebagai kondisi untuk kueri:

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

Yang harus kembali

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

Kolom bersarang juga dapat ditanyakan, seperti posting dengan jenis Posting, Anda dapat meminta judulnya saja:

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

Dan itu harus mengembalikan semua jenis Penulis yang cocok dengan Nigeria yang mengembalikan negara dan array posting yang berisi objek hanya dengan bidang judul.

Gatsby dengan GraphQL

Untuk menghindari overhead memiliki server/layanan yang menyajikan data yang dapat diubah oleh GraphQL, Gatsby mengeksekusi kueri GraphQL pada waktu pembuatan. Data diberikan ke komponen selama proses pembuatan, membuatnya tersedia di dalam browser tanpa server.

Namun, Gatsby dapat berjalan sebagai server yang dapat di-query oleh klien GraphQL lainnya, seperti GraphiQL, di browser.

Cara Gatsby Berinteraksi Dengan GraphQL

Ada dua tempat di mana Gatsby dapat berinteraksi dengan GraphQL, melalui file API gatsby-node.js, dan melalui komponen halaman.

gatsby-node.js

API createPage dapat dikonfigurasi sebagai fungsi yang akan menerima pembantu graphql sebagai bagian dari item dalam argumen pertama yang diteruskan ke fungsi.

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

Pada kode di atas, kita telah menggunakan helper GraphQL untuk mengambil file penurunan harga dari lapisan data Gatsby. Dan kita bisa menyuntikkan ini untuk membuat halaman dan memodifikasi data yang ada di dalam lapisan data Gatsby.

Komponen Halaman

Komponen halaman di dalam direktori /pages atau template yang dirender oleh tindakan createPage API dapat mengimpor graphql dari modul gatsby dan mengekspor pageQuery . Pada gilirannya, Gatsby akan menyuntikkan data prop baru ke properti komponen halaman yang berisi data yang diselesaikan.

 import React from "react"; import { graphql } from "gatsby"; const Page = props => { return
{JSON.stringify(props.data)}
; }; ekspor const pageQuery = graphql` permintaan { ... } `; ekspor Halaman default;

Di Komponen Lain

Komponen lain dapat mengimpor komponen graphql dan StaticQuery dari modul gatsby , merender <StaticQuery/> meneruskan props kueri yang mengimplementasikan helper Graphql dan merender untuk mendapatkan data yang dikembalikan.

 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;

Membangun Blog Penerbitan Gatsby Modern Dan Canggih

Pada bagian ini kita akan berjalan melalui proses pembuatan blog yang mendukung penandaan, kategorisasi, pagination dan pengelompokan artikel oleh penulis. Kami akan menggunakan plugin ekosistem Gatsby untuk menghadirkan beberapa fitur dan menggunakan logika dalam kueri GraphQL untuk membuat blog penerbit yang siap untuk publikasi banyak penulis.

Versi final dari blog yang akan kita buat dapat ditemukan di sini, juga kodenya di-host di Github.

Inisialisasi Proyek

Seperti situs web Gatsby lainnya, kami menginisialisasi dari starter, di sini kami akan menggunakan starter lanjutan tetapi dimodifikasi untuk memenuhi kasus penggunaan kami.

Pertama klon repo Github ini, ubah cabang kerja ke dev-init, lalu jalankan npm run develop dari folder proyek untuk memulai server pengembangan yang membuat situs tersedia di 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

Mengunjungi https://localhost:8000 akan menampilkan beranda default untuk cabang ini.

Membuat Konten Postingan Blog

Beberapa konten posting yang termasuk dalam repositori proyek dapat diakses di cabang dev-blog-content. Organisasi direktori konten terlihat seperti ini /content/YYYY_MM/DD.md , yang mengelompokkan pos menurut bulan yang dibuat dalam setahun.

Konten postingan blog memiliki title , date , author , category , tags sebagai frontmatternya, yang akan kita gunakan untuk membedakan sebuah postingan dan melakukan beberapa pemrosesan lebih lanjut, sedangkan konten lainnya adalah badan postingan.

 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.

Menampilkan Konten Posting

Sebelum kita dapat merender posting Markdown kita dalam HTML, kita harus melakukan beberapa pemrosesan. Pertama, memuat file ke penyimpanan Gatsby, mem-parsing MD ke HTML, menautkan dependensi gambar, dan suka. Untuk memudahkan ini, kami akan menggunakan sejumlah plugin oleh ekosistem Gatsby.

Kita dapat menggunakan plugin ini dengan memperbarui gatsby-config.js di root proyek agar terlihat seperti ini:

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

Kami telah menginstruksikan gatsby untuk menyertakan plugin untuk membantu kami melakukan beberapa tindakan, terutama menarik file dari folder /static untuk file statis dan /content untuk posting blog kami. Juga, kami telah menyertakan plugin transformer komentar untuk mengubah semua file yang diakhiri dengan .md atau .markdown menjadi simpul dengan semua bidang komentar untuk merender penurunan harga sebagai HTML.

Terakhir, kami menyertakan plugin dalam pengoperasian pada node yang dihasilkan oleh gatsby-transformer-remark .

Menerapkan File API gatsby-config.js

Ke depan, di dalam gatsby-node.js di root proyek, kita dapat mengekspor fungsi bernama createPage dan memiliki konten fungsi untuk menggunakan helper graphQL untuk menarik node dari lapisan konten GatsbyJS.

Pembaruan pertama untuk halaman ini akan mencakup memastikan bahwa kita memiliki set slug pada node komentar MarkDown. Kami akan mendengarkan API onCreateNode dan membuat simpul dibuat untuk menentukan apakah itu jenis MarkdownRemark sebelum kami memperbarui simpul untuk menyertakan siput dan tanggal yang sesuai.

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

Daftar Postingan

Pada titik ini, kita dapat menerapkan API createPages untuk meminta semua penurunan harga dan membuat halaman dengan jalur seperti slug yang telah kita buat di atas. Lihat di 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, }); } };

Dalam fungsi createPages , kita menggunakan helper graphql yang disediakan oleh Gatsby untuk mengkueri data dari lapisan konten. Kami menggunakan kueri Graphql standar untuk melakukan ini dan meneruskan kueri untuk mendapatkan konten dari tipe allMarkdownRemark . Kemudian bergerak maju untuk mengurutkan posting berdasarkan tanggal yang dibuat.

Kami kemudian menarik properti postPerPage dari objek konfigurasi yang diimpor, yang digunakan untuk membagi total posting ke jumlah posting yang ditentukan untuk satu halaman.

Untuk membuat halaman listingan yang mendukung pagination, kita harus memasukkan limit, pageNumber, dan jumlah halaman yang akan dilewati ke komponen yang akan merender daftar. Kami mencapai ini menggunakan properti konteks dari objek konfigurasi createPage . Kami akan mengakses properti ini dari halaman untuk membuat kueri graphql lain untuk mengambil posting dalam batas.

Kita juga dapat melihat bahwa kita menggunakan komponen template yang sama untuk listingan, dan hanya path yang berubah menggunakan indeks dari array chunk yang telah kita definisikan sebelumnya. Gatsby akan meneruskan data yang diperlukan untuk pencocokan URL yang diberikan /{chunkIndex} , sehingga kami dapat memiliki / untuk sepuluh posting pertama, dan /2 untuk sepuluh posting berikutnya.

Beranda Blog Modern
Beranda blog modern (Pratinjau besar)

Rendering Postingan Daftar

Komponen yang merender halaman ini dapat ditemukan di src/templates/singlePost/index.js dari folder proyek. Itu juga mengekspor pembantu graphql yang menarik batas dan parameter kueri halaman yang diterimanya dari proses createPages untuk meminta gatsby untuk posting dalam rentang halaman saat ini.

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

Halaman Posting

Untuk melihat konten halaman, kita perlu membuat halaman secara terprogram di dalam File API gatsby-node.js . Pertama, kita harus mendefinisikan komponen baru untuk merender konten, untuk ini, kita memiliki 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 } } } `;

Sekali lagi, kami menggunakan pembantu graphQL untuk menarik halaman dengan kueri slug yang akan dikirim ke halaman melalui createPages API.

Selanjutnya, kita harus menambahkan kode di bawah ini ke gatsby-node.js di akhir fungsi createPages API.

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

Dan kita dapat mengunjungi '/{pageSlug}' dan membuatnya membuat konten file penurunan harga untuk halaman itu sebagai HTML. Sebagai contoh, https://localhost:8000/the-butterfly-of-the-edge harus memuat HTML yang dikonversi untuk penurunan harga di: content/2020_05/01.md , mirip dengan semua slug yang valid. Besar!

Halaman Posting Blog Modern
Halaman posting blog modern (Pratinjau besar)

Merender Kategori Dan Tag

Komponen template postingan tunggal memiliki tautan ke halaman dalam format /categories/{categoryName} untuk mencantumkan postingan dengan kategori serupa.

Pertama-tama kita dapat menangkap semua kategori dan tag saat kita membangun halaman posting tunggal di file gatsby-node.js , kemudian membuat halaman untuk setiap kategori/tag yang tertangkap dengan meneruskan nama kategori/tag.

Modifikasi pada bagian untuk membuat halaman posting tunggal di gatsby-node.js terlihat seperti ini:

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

Dan di dalam komponen untuk membuat daftar posting berdasarkan tag, kita dapat memiliki permintaan ekspor pageQuery graphql untuk posting, termasuk tag itu dalam daftar tagnya. Kami akan menggunakan fungsi filter dari graphql dan operator $in untuk mencapai ini:

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

Dan kami memiliki proses yang sama dalam komponen daftar kategori, dan perbedaannya adalah kami hanya perlu menemukan di mana kategori tersebut cocok dengan apa yang kami berikan padanya.

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

Terlihat, di dalam komponen tag dan kategori, kami membuat tautan ke halaman posting tunggal untuk membaca konten posting lebih lanjut.

Halaman posting tunggal Hello World dengan tag
Postingan modern dengan tag kategori (Pratinjau besar)

Menambahkan Dukungan Untuk Penulis

Untuk mendukung banyak penulis, kami harus membuat beberapa modifikasi pada konten posting kami dan memperkenalkan konsep baru.

Muat File JSON

Pertama, kita harus dapat menyimpan konten penulis dalam file JSON seperti ini:

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

Kami akan menyimpannya di direktori penulis di root proyek kami sebagai /authors . Perhatikan bahwa penulis JSON memiliki mdField yang akan menjadi pengidentifikasi unik untuk bidang penulis yang akan kami perkenalkan ke konten blog penurunan harga; ini memastikan bahwa penulis dapat memiliki beberapa profil.

Selanjutnya, kita harus memperbarui plugin gatsby-config.js menginstruksikan gatsby-source-filesystem untuk memuat konten dari direktori authors/ ke dalam Files Node.

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

Terakhir, kita akan menginstal gatsby-transform-json untuk mengubah file JSON yang dibuat agar mudah ditangani dan diproses dengan benar.

 npm install gatsby-transformer-json --save

Dan sertakan di dalam plugin gatsby-config.js ,

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

Menanyakan Dan Membuat Halaman Penulis

Untuk memulainya, kita perlu menanyakan semua penulis di direktori authors/ kita di dalam gatsby-config.js yang telah dimuat ke dalam lapisan data, kita harus menambahkan kode di bawah ini untuk createPages fungsi API halaman

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

Dalam cuplikan ini, kami menarik semua penulis dari tipe allAuthorsJson, lalu, memanggil forEach pada node untuk membuat halaman tempat kami melewati mdField untuk membedakan penulis dan authorDetails untuk informasi lengkap tentang penulis.

Membuat Postingan Penulis

Dalam komponen yang merender halaman yang dapat ditemukan di src/templates/authorsListing/index.jsx , kami memiliki konten di bawah ini untuk file

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

Dalam kode di atas, kami mengekspor pageQuery seperti yang kami lakukan, untuk membuat kueri GraphQL untuk mengambil posting yang cocok dengan penulis, kami menggunakan operator $eq untuk mencapai ini, menghasilkan tautan ke satu halaman posting untuk dibaca lebih lanjut.

Halaman Penulis Blog Modern
Halaman penulis blog modern (Pratinjau besar)

Kesimpulan

Di Gatsby, kita dapat mengkueri data apa pun yang ada di dalam lapisan akses datanya dengan menggunakan kueri GraphQL dan meneruskan variabel menggunakan beberapa konstruksi yang ditentukan oleh arsitektur Gatsby. kami telah melihat bagaimana kami dapat menggunakan pembantu graphql di berbagai tempat dan memahami pola yang digunakan secara luas untuk meminta data di situs web Gatsby dengan bantuan GraphQL.

GraphQL sangat kuat dan dapat melakukan hal-hal lain seperti mutasi data di server. Gatsby tidak perlu memperbarui datanya saat runtime, sehingga tidak mendukung fitur mutasi GraphQL.

GraphQL adalah teknologi yang hebat, dan Gatsby membuatnya sangat menarik untuk digunakan dalam kerangka kerja mereka.

Referensi

  • Dukungan Gatsby untuk GraphQL
  • Mengapa Gatsby menggunakan GraphQL
  • Konsep GraphQL di Gatsby
  • Bagaimana GraphQL: Konsep Dasar
  • Bahasa Definisi Skema Di GraphQL
  • Pengantar GraphQL
  • Pemula Tingkat Lanjut Gatsby