静态博客生成器
实现一个静态博客生成的工具,本质上还是实现一个后端博客系统,唯一不同从数据库变成了 markdown
文件,原本读取数据库的操作,变成了读取本地 markdown
文件,后者通过 markdown
渲染工具转换成 html
然后插入到定义好的主题模板中去,最后导出 html
数据。
Markdown 数据
遍历一个定义好的文件夹,找出其中所有的 .md
文件,将文件名称作为网页地址后面的一部分 (slug)。此时已经有了 slug
和文章内容了,还需要一些诸如:标题、日期、分类、标签之类的参数。比如 hexo 采用了下面的格式来实现,然后通过正则获取到这部分的数据,最后解析成 JSON
数据:
title: Hello World
date: 2019-11-11
tags: []
categories: category
---
这样就实现了原本通过 select * from posts order by created desc
来获取到的所有文章内容。
路由
获取到文章内容和在主题或者全局设定好的布局配置之后,需要注册路由,将对应的数据展示出来,这样才可以在写主题、文章时实时预览前端的效果。
以 express 为例,文章部分的路由可以如下定义:
const app = express()
posts.forEach(row => {
app.get(`/${row.slug}`, (_, res) => {
res.render('post.ejs', {
title: row.title,
content: row.content,
date: row.date,
categories: row.categories,
tags: row.tags
})
})
})
模板
以 hexo
为例,hexo
采用了 ejs 这种模板,它可以实现循环、条件判断、引入其他模板等功能,这样我们可以主题将模板拆分到足够小的颗粒。
<%- include header.ejs %>
<h1><%= title %></h1>
<div><%= created %></div>
<div class="post">
<%- content %>
</div>
<%- include footer.ejs %>
中间件
我们虽然可以在每个路由下,通过 res.render
注入所有需要所有文章、网站配置、主题配置等数据。既然是重复的行为,可以使用中间件来实现,将所有数据绑定到 res.locals
上,就可以提供给 ejs
渲染输出。
// middware.js
module.exports = () => {
return (_, res, next) => {
res.locals = {}
next()
}
}
使用中间件也很简单:
// router.js
app.get('/', middware, (req, res) => {
})
静态页面
在完善了主题之后,只需要将路由中所有注册过的页面重新循环一遍,将 ejs
渲染成 html
保存成相应的文件即可,最后可以通过 CI 部署到指定的网站即可。