使用Gatsby + Ant desgin + TypeScript + GraphQL 开发静态博客系统
为什么选择Gatsby
- 开箱即用
- 纯静态站点访问快
- 使用React + GraphQL + Pwa 等新技术
- 部署简单
- 插件丰富
Gatsby开发流程
安装流程
1.安装工具 Gatsby CLI
npm install -g gatsby-cli
2.查看版本
gatsby --version
3.创建项目
gatsby new project-name
4.启动项目
gatsby develop or npm start
5.访问项目
GraphiQL 查询界面 http://localhost:8000/___graphql
项目目录说明
├── json # 项目数据
│ └── markdown # markdown文档
│ └── html # 文档分类
├── public # build之后的项目目录
└── src # 资源文件夹
├── components # 组件
├── images # 图片
├── less # 样式文件
├── pages # 页面
├── templates # 模板
└── types # typescript类型
支持less
在 gatsby 应用中支持 less,需要依赖gatsby-plugin-less,只需要下载之后在plugins加入这个插件就可以支持了。
1.安装插件:
npm install --save gatsby-plugin-less
2.插件配置:
gatsby-config.js
plugins: [
`gatsby-plugin-less`
...
]
3.使用less
在 src/components/Layout.tsx
文件中
import "../less/layout.less"
在 src/less/layout.less
中
// 页面主要布局
.layout{
width:100%;
overflow-y: scroll;
}
布局
- 引入Ant desgin
npm install antd
2.配置主题
在 gatsby-config.js
配置ant 主题
plugins: [
{
resolve: `gatsby-plugin-less`,
options: {
lessOptions: {
modifyVars: {
'primary-color': '#1DA57A',
'link-color': '#1DA57A',
},
javascriptEnabled: true,
},
},
},
]
3.创建布局文件
在 src/components/
创建 Layout.tsx
/**
* Layout component that queries for data
* with Gatsby's useStaticQuery component
*
* See: https://www.gatsbyjs.com/docs/use-static-query/
*/
import * as React from "react"
import PropTypes from "prop-types"
import { Link, useStaticQuery, graphql } from "gatsby"
import { StaticImage } from "gatsby-plugin-image"
import "../less/layout.less"
import { Layout, Menu, Space } from 'antd'
const { Header, Footer, Content } = Layout
const LayoutDefault: React.FC = ({ children }) => {
const data = useStaticQuery(graphql`
query SiteTitleQuery {
site {
siteMetadata {
title
}
}
}
`)
return (
<Layout className="layout">
<Header className="header">
<Link to="/" className="logo">
<StaticImage
src="../images/3pixel_logo.png"
width={110}
formats={["auto", "webp", "avif"]}
alt={data.site.siteMetadata?.title || `Title`}
/>
</Link>
<Menu
className="menu"
theme="dark"
mode="horizontal">
<Menu.Item key="1">
<Link to="/" activeClassName="cur">首页</Link>
</Menu.Item>
<Menu.Item key="2">
<Link to="/html" activeClassName="cur">Html</Link>
</Menu.Item>
</Menu>
</Header>
<Content className="content">
{children}
</Content>
<Footer className="footer">
<Space direction="vertical">
<div>© {new Date().getFullYear()} <a href="https://beian.miit.gov.cn">陕ICP备14011119号-2</a></div>
<Space>
博客支持:
<a href="https://www.gatsbyjs.com">Gatsby</a>
<a href="https://react.docschina.org/">React</a>
<a href="https://ant.design/index-cn">Ant Desgin</a>
<a href="https://www.tslang.cn/">TypeScript</a>
</Space>
</Space>
</Footer>
</Layout>
)
}
LayoutDefault.propTypes = {
children: PropTypes.node.isRequired,
}
export default LayoutDefault
4.使用布局
在 src/pages
下创建 404.tsx
如下:
import * as React from "react"
import Layout from "../components/Layout"
import FixedContent from "../components/FixedContent"
import Seo from "../components/Seo"
import { PageProps, Link } from "gatsby"
import { Result, Button } from 'antd'
const NotFoundPage: React.FC<PageProps> = () => (
<Layout>
<Seo title="404: Not found" />
<FixedContent>
<Result
status="404"
title="404"
subTitle="对不起页面没有找到"
extra={
<Link to="/">
<Button type="primary">返回首页</Button>
</Link>
}
/>
</FixedContent>
</Layout>
)
export default NotFoundPage
添加MD文档
- 在
json/markdown
下面创建markdown文件如: blog1.md
---
date: "2021-09-15"
title: "第一篇测试文章"
description: "第一篇测试文章摘要"
---
> 测试文章摘要
## 测试标题1
sdfsfsd
## 测试标题2
- 测试标题1
- 测试标题2
2.插件配置
安装 gatsby-source-filesystem
可检索提取项目中的Md和YML/YMAL等文件,注意要配置其path包含放MD文件的位置
安装 gatsby-transformer-remark
可对提取的MD类文件解析成json等格式的数据源
npm install gatsby-source-filesystem gatsby-transformer-remark
gatsby-config.js文件参考⤵️
plugins: [
{
resolve: "gatsby-source-filesystem",
options: {
name: "data",
path: `${__dirname}/json/markdown/`
}
},
{
resolve: 'gatsby-transformer-remark',
options: {
plugins: [
{
resolve: `gatsby-remark-images`,
options: {
maxWidth: 590,
linkImagesToOriginal: false,
},
},
]
}
},
]
4.解析MD文件
在 src/templates
下创建 页面模板blog.tsx
import * as React from "react"
import Layout from "../components/Layout"
import Seo from "../components/Seo"
import { PageProps, graphql } from "gatsby"
import type { BlogDetail } from '../types/blog'
import FixedContent from "../components/FixedContent"
import PageSection from "../components/PageSection"
import { Breadcrumb } from 'antd';
type DataProps = {
markdownRemark: BlogDetail
}
const Blog: React.FC<PageProps<DataProps>> = ({ data }) => {
const post = data.markdownRemark
return (
<Layout>
<Seo title="post" />
<FixedContent>
<Breadcrumb className="breadcrumb">
<Breadcrumb.Item href="/">首页</Breadcrumb.Item>
<Breadcrumb.Item>{post.frontmatter.title}</Breadcrumb.Item>
</Breadcrumb>
<PageSection>
<h1>{post.frontmatter.title}</h1>
<p>{post.frontmatter.date}</p>
<p>{post.frontmatter.description}</p>
<div dangerouslySetInnerHTML={{ __html: post.html }} />
</PageSection>
</FixedContent>
</Layout>
)
}
export default Blog
export const query = graphql`
query($slug: String!) {
markdownRemark(fields: { slug: { eq: $slug } }) {
html
id
fields {
slug
}
frontmatter {
date(formatString: "YYYY-MM-DD", locale: "zh-CN")
description
title
}
}
}
`
同时在gatsby-node.js
文件中利用createPages加上页面解析
const path = require(`path`)
const { createFilePath } = require(`gatsby-source-filesystem`)
exports.onCreateNode = ({ node, getNode, actions }) => {
const { createNodeField } = actions
if (node.internal.type === `MarkdownRemark`) {
const slug = createFilePath({ node, getNode, basePath: `pages` })
createNodeField({
node,
name: `slug`,
value: slug,
})
}
}
exports.createPages = async ({ graphql, actions }) => {
const { createPage } = actions
const result = await graphql(`
query {
allMarkdownRemark {
edges {
node {
fields {
slug
}
}
}
}
}
`)
result.data.allMarkdownRemark.edges.forEach(({ node }) => {
createPage({
path: node.fields.slug,
component: path.resolve(`./src/templates/blog.tsx`),
context: {
// Data passed to context is available
// in page queries as GraphQL variables.
slug: node.fields.slug,
},
})
})
}
5.MD代码块高亮
增加gatsby-remark-prismjs
插件
npm install gatsby-remark-prismjs
在 gatsby-config.js
中配置插件
plugins: [
{
resolve: "gatsby-transformer-remark",
options: {
plugins: [
`gatsby-remark-images`,
{
resolve: `gatsby-remark-prismjs`,
options: {
classPrefix: "language-",
inlineCodeMarker: null,
aliases: {},
showLineNumbers: false,
noInlineHighlight: false,
languageExtensions: [
{
language: "superscript",
extend: "javascript",
definition: {
superscript_types: /(SuperType)/,
},
insertBefore: {
function: {
superscript_keywords: /(superif|superelse)/,
},
},
},
],
prompt: {
user: "root",
host: "localhost",
global: false,
},
escapeEntities: {},
},
},
]
}
},
]
在 gatsby-browser.js
中增加样式
require("prismjs/themes/prism-solarizedlight.css")
GraphQL 数据
使用 http://localhost:8000/___graphql
查询所需数据
1.在组件中使用GraphQL, 如: src/components/Layout.tsx
const data = useStaticQuery(graphql`
query SiteTitleQuery {
site {
siteMetadata {
title
}
}
}
`)
2.在页面中使用GraphQL, 如: src/pages/index.tsx
export const query = graphql`
query {
allMarkdownRemark(sort: { order: DESC, fields: [frontmatter___date] }) {
totalCount
edges {
node {
id
fields {
slug
}
frontmatter {
date(formatString: "YYYY-MM-DD", locale: "zh-CN")
description
title
}
}
}
}
}
`
Gatsby部署
- 使用
gh-pages
插件, 创建gh-pages分支, 只把编译后的同步到仓库
安装到本地
npm install gh-pages --save-dev
配置 package.json
"scripts": {
"deploy": "gatsby build && gh-pages -d public -b master -r https://git.avenirzheng.net/blog.git"
},
2.部署到腾讯云轻服务器
创建域名: gatsby.blog.3pixellab.com
配置Nginx:
server
{
listen 80;
server_name gatsby.blog.3pixellab.com;
index index.html;
root /www/wwwroot/gatsby.blog.3pixellab.com/;
#SSL-START SSL相关配置,请勿删除或修改下一行带注释的404规则
#error_page 404/404.html;
#SSL-END
#ERROR-PAGE-START 错误页配置,可以注释、删除或修改
#error_page 404 /404.html;
#error_page 502 /502.html;
#ERROR-PAGE-END
#PHP-INFO-START PHP引用配置,可以注释或修改
include enable-php-00.conf;
#PHP-INFO-END
#REWRITE-START URL重写规则引用,修改后将导致面板设置的伪静态规则失效
include /www/server/panel/vhost/rewrite/gatsby.blog.3pixellab.com.conf;
#REWRITE-END
#禁止访问的文件或目录
location ~ ^/(\.user.ini|\.htaccess|\.git|\.svn|\.project|LICENSE|README.md)
{
return 404;
}
#一键申请SSL证书验证目录相关设置
location ~ \.well-known{
allow all;
}
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 30d;
error_log /dev/null;
access_log /dev/null;
}
location ~ .*\.(js|css)?$
{
expires 12h;
error_log /dev/null;
access_log /dev/null;
}
access_log /www/wwwlogs/gatsby.blog.3pixellab.com.log;
error_log /www/wwwlogs/gatsby.blog.3pixellab.com.error.log;
}
创建文件夹 gatsby.blog.3pixellab.com
并拉去代码, 切换到 'gh-pages' 分支
3.使用npm run deploy
就可以发布到生产环境了
参考文档
总结
项目地址: gitee.com/kermityu/ga…
这个博客项目让我全方位的了解了Gatsby
, 并实际使用了GraphQL
TypeScript
等新的技术, 让自己也有了更高的提升
目前遗留一个问题
- 页面切换的时候,logo图片会闪烁