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页面的实现类似。
Leave Gatsby中的页面生成 to:
Read more #cn posts
Best Posts From aafeng
We have not curated any of aafeng's posts yet. But you can encourage our curation team to review posts by visiting them regularly and by referring other readers. Because we give priority to frequently read content.