程序员,旅游爱好者。 个人网站:https://www.aafeng.uk
Gatsby中的页面生成
Gatsby是目前非常流行的静态页面生成框架。 页面生成是其最核心功能之一。 下面就来说说如何在Gatsby中自动生成文章页面,Category分类页面,以及tags标签页面。
Source: Gatsby官网
配置
gatsby-config.js中的配置
首先需要声明对markdown文件的监测,这样gatsby才能获取markdown中的frontmatter信息,比如slug:
{ resolve: `gatsby-source-filesystem`, options: { name: `posts`, path: `${__dirname}/src/posts` } }
动态生成页面文件
gatsby-node.js
接下来就可以在gatsby-node.js中通过graphql来获取所有markdown的元数据,也就是frontmatter信息:
const { data } = await graphql(` query posts { allMarkdownRemark { nodes { frontmatter { slug category tag } } } } `)
通过上面的graphql,就可以获取最为重要的信息,比如slug,这样我们就知道将要生成的文件名了。
接下来就可以调用actions.createPage来创建页面了:
data.allMarkdownRemark.nodes.forEach(node => { actions.createPage({ path: `/posts/${node.frontmatter.slug}`, component: path.resolve('./src/templates/post.js'), context: { slug: node.frontmatter.slug } }) })
这里需要的模板文件: ./src/templates/post.js
首先需要通过传递过来的slug查询相应页面:
export const query = graphql` query PageDetails($slug: String) { markdownRemark(frontmatter: {slug: {eq: $slug}}) { html frontmatter { category tag title thumbnail { childImageSharp { fluid { ...GatsbyImageSharpFluid } } } } } } `
接下来就可以生成页面了:
import React from "react" import { graphql } from 'gatsby' import Img from "gatsby-image" import Layout from "../components/Layout" import '../styles/post.css' const Post = ({data}) => { const { html } = data.markdownRemark const { title, category, tag, thumbnail } = data.markdownRemark.frontmatter return ( <Layout> <div> <h2>{title}</h2> <p>类别: {category}</p> <p>标签: {tag}</p> <div> </div> <div dangerouslySetInnerHTML={{__html: html}} /> </div> </Layout> ) } export default Post
这时重新启动gatsby,就可以访问页面了: /posts/xxxxxx 。 如果运行gatasby build就可以看到在public目录中新生成的页面。
生成自定义的category/ tag页面
在很多博客站点中,都提供针对某一个category / tag的页面,这样可以把同类的文章汇总到一起。
首先还是在gatsby-node.js中的预处理:
categories = new Set() tags = new Set() data.allMarkdownRemark.nodes.forEach(node => { actions.createPage({ path: `/${node.frontmatter.category}/${node.frontmatter.slug}`, component: path.resolve('./src/templates/details.js'), context: { slug: node.frontmatter.slug } }) categories.add(node.frontmatter.category); node.frontmatter.tag.forEach(t => { tags.add(t); }) }) categories.forEach(category => { actions.createPage({ path: `/categories/${category}`, component: path.resolve('./src/templates/category.js'), context: { category: category } }) }) tags.forEach(tag => { actions.createPage({ path: `/tags/${tag}`, component: path.resolve('./src/templates/tag.js'), context: { tag: tag } }) })
接下来是在模板文件src/templates/tag.js中的处理:
import React from "react" import { graphql, Link } from 'gatsby' import Img from "gatsby-image" const Tag = ({pageContext, data}) => { const { tag } = pageContext; const posts = data.posts.nodes; return ( <> <div> <h3>标签:{tag}</h3> <div> {posts.map((post) => { const {frontmatter} = post; return( <div key={post.id}> <h3> <Link to={`/${post.frontmatter.category}/${post.frontmatter.slug}`}> {frontmatter.title} </Link> </h3> <p>发布日期: {frontmatter.date.substring(0,10)}</p> <p>类别: <Link to={`/categories/${frontmatter.category}`}> {frontmatter.category} </Link> </p> <p>标签:{ frontmatter.tag.map(t => { return ( <Link to={`/tags/${t}`}> <span className="tag">{t}</span> </Link> ) }) }</p> </div> ) })} </div> </div> </> ) } export default Tag export const query = graphql` query TagQuery($tag: String) { posts: allMarkdownRemark( filter: {frontmatter: {tag: {eq: $tag}}} sort: {fields: frontmatter___date, order: DESC} ) { nodes { frontmatter { title slug keywords thumbnail { childImageSharp { fluid { ...GatsbyImageSharpFluid } } } category tag date } id } } } `
category页面的实现类似。
喜欢我的文章吗?
别忘了给点支持与赞赏,让我知道创作的路上有你陪伴。
发布评论…