前几天跟老铁们聊天,有位老铁说想弄一个博客只靠 SEO 被搜索,想再次回归曾经那份朴素。于是我又想起了我那放置许久的博客。
闲聊之余网上找了找有没有不错的静态博客框架可用,毕竟好久没有更新博客的框架了。 机缘巧合,看到的文章推荐使用的第一项就是 Gatsby,上官网看了看貌似还不错。后来才知道 React 官网也是用这个框架搭建的 😝。
正好年前有点闲暇时间,着手弄了弄。从 jekyll、hexo、octopress,现在更新到了 Gatsby。以下是一点点经验,分享给大家。
先安装项目工具:
npm i -g gatsby-cli
生成项目:
npm new [your project name]
可以查看目录下的 package.json
了解项目命令。
运行如下命令,就能看到项目工具生成的基础博客站。
gatsby develop
简单说明一下项目结构:
目录/文件 | 说明 |
---|---|
src/components | 放置组件的目录 |
src/pages | 基础方式渲染的页面目录(根据文件名形成路由) |
gatsby-config.js | 中间件配置及网站基本信息配置文件 |
gatsby-node.js | 高级方式渲染页面(根据路径配置方式生成路由) |
<以下是后续添加的部分> | |
src/queries | Graphql 查询语句放置目录 |
src/templates | 高级方式渲染页面所用的模版放置目录 |
static | 发布时自动合并到发布目录的静态文件放置目录 |
deploy.sh | 正式发布站点的脚本 |
先把文件 src/components/header
转成目录 src/components/Header/
。
将原文件里的代码拷入 index.jsx
再适当的修改修改。
...Component{superpropsthisstate =currentMenu: 'home'}{const pathname = windowlocationconst extract = pathname1thisif extract === '' || /^[0-9]+$/thiselse if extract === 'about'thiselse if extract === 'blog' || extractlength === 24thiselsethis}{const siteTitle = thispropsconst currentMenu = thisstatereturn <div className="header"><div className="container"><ul><li className="site-title"><h1><Link to="/">siteTitle</Link></h1></li><li className=currentMenu === 'home' ? 'menu-item currentMenu' : 'menu-item'><h3><Link to="/">Home</Link></h3></li><li className=currentMenu === 'blog' ? 'menu-item currentMenu' : 'menu-item'><h3><Link to="/blog">Blog</Link></h3></li><li className=currentMenu === 'about' ? 'menu-item currentMenu' : 'menu-item'><h3><Link to="/about">About</Link></h3></li></ul></div></div>}...
增加了当前菜单的 state 进行菜单状态管理。
ul > li 横向序列化,第一个用作网站标题,其他的作为菜单项使用。
注:
1. 首页判断部分,后续要增加首页翻页功能,所以增加了数字判断。
2. 博文判断部分,准备用24位随机码作为每个文章的地址。所以除了 blog 还增加了随机码长度的判断。
样式部分就根据个人喜好开发就好了。
作为博客,最主要的还是博文部分,先把博文部分弄出来再说。
之前的博文都是用 markdown 写的,先安装 markdown 解析工具并进行配置。
npm i gatsby-source-filesystemnpm i gatsby-transformer-remarknpm i gatsby-plugin-catch-links
修改 gatsby 插件配置 gatsby-config.js
:
...plugins:...resolve: 'gatsby-source-filesystem'options:name: 'pages'path: `/src/pages`'gatsby-transformer-remark''gatsby-plugin-catch-links'......
配置好之后,在 src/pages
目录里直接创建 md 文件或是创建目录并在里边创建 md 文件都可以。markdown 解析部分完成了。
如果留意观察过启动时控制台的提示,就知道访问 http://localhost:8000/___graphql
就能够进行 GraphiQL 查询了。
先看一下博文头部信息:
---path : '/yp63Vswica5FHmJGE479XP5k'title : '用 Gatsby 搭建静态博客 1'date : 2019-01-31 18:56:00 +0800comments : truecategories : programmingauthor : Sir0xbtags : [Gatsby, React]---
这些信息很重要,都是一会儿要被查询的字段。
打开 http://localhost:8000/___graphql
,在左侧搜索条件输入:
{edgesnodeidhtmlfrontmatterpathtitledatecommentsauthortagsexcerpt}
看到查询结果大概就明白各个字段代表什么意思,不做过多解释。
有了能够正常运行的查询表达式,可以开始我们的渲染工作了。
还记得改造菜单时候添加了一个路径 /blog
吗?
在 src/pages
里创建一个 blog.js
const BlogPage =<div><h1>This is the blog page</h1>dataallMarkdownRemarkedges</div>const pageQuery = graphql`{allMarkdownRemark(sort: {fields: [frontmatter___date], order: DESC}) {edges {node {idhtmlfrontmatter {pathtitledatecommentsauthortags}excerpt}}}}`
Gatsby 用 GraphiQL 查询文件的逻辑就是,通过导出 pageQuery 进行数据查询,并把结果注入到当前 Component 的 props 的 data 里。
重新启动之后,点击菜单 blog
看到所有文章列表了。
点击博文发现页面 404 了。原因是在 src/pages
里没有找到我们24位随机码路径对应的文件。
这时候我们就要用到高级方式渲染页面的功能了。
我们先做一个博文预览的模版文件 src/templates/post.js
const Template = {const post = datamarkdownRemarkreturn <Layout><SEO title=postfrontmattertitle /><buttonclassName="go-back"onClick= { windowhistory }>Go back</button><div className="blog-post"><h1>postfrontmattertitle</h1><h4>Posted by postfrontmatterauthor on postfrontmatterdate</h4><div dangerouslySetInnerHTML=__html: posthtml></div></div></Layout>}const postQuery = graphql`query BlogxxxPostByPath($path: String!) {markdownRemark(frontmatter: { path: { eq: $path } }) {htmlfrontmatter {pathtitleauthordate}}}`
我们把 blog.js
里面的查询抽离到 src/queries/queryAll.js
里。
blog.js
文件里的查询先不动。(blog.js
文件后续就放弃不用了)
打开 gatsby-node.js
文件。
const path =const queryAll =exports {const createPage = boundActionCreatorsreturn {}}
重启之后再点开文章,是不是可以正常渲染了。
写了多年的博客那么多的博文,如果一次性全部显示出来就不友好了。
解决方案就是加个翻页器,先把 gatsby 的翻页器工具安上。
npm i gatsby-paginate
翻页器功能可以使用官网 Demo 里提供的代码,当然也可以自己开发。
我比较喜欢前后都有《最前》、《最后》以及《上一页》、《下一页》按钮,页码部分低位至少留有两个页码,高位也至少留有两个页码,并且当前页码的前后各留有两个页码的翻页方式。
那我们先把翻页器组件实现一下。src/components/Paginator/index.jsx
const getRandomStr = {let text = ''let possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'for let i = 0; i < len; i++text += possiblereturn text}const Paginator = {let result =resultif index <= 2resultelseresultif pageCount < 11Objectelseif index <= 5// 低数 index + 2 高位两个Objectresultresultresultelse if index >= pageCount - 4// 低位两个 高位 index - 2 到顶resultresultresult// pageCount - (index - 2) + 1 = pageCount - index + 3Objectelse// 低位两个 中间 index - 2 ~ index + 2 高位两个resultresultresultresultresultresultresultresultresultresultresultif index === pageCountresultelseresultresultreturn <div className="paginator">result</div>}
注:因为翻页器可能会用在首页,也可能用在博文页,所以传入了相对路径 relativeUrl
。
将 src/pages/blog.js
更名或删除。我们要通过高级方式生成博文页面,不再使用原来的页面了。
再做一个带翻页器的博文页面渲染模版。src/templates/posts.js
const Template = {constgroupindexpageCount} = pageContextreturn <Layout><SEO title="Blog" /><Paginator index=index pageCount=pageCount relativeUrl="/blog" />group<Paginator index=index pageCount=pageCount relativeUrl="/blog" /></Layout>}
有了翻页器组件,有了模版,就差数据了。
修改下 gatsby-node.js
const path =const createPaginatedPages =const queryAll =exports {const createPage = actionsreturn {}}
注:由于 gatsby-paginate
要求的 Gatsby 版本要比默认的高,所以我把 Gatsby 版本升级到了最高。于是这里有了点变化。原先的 boundActionCreators
变成了 actions
。