ZHANGYU.dev

October 14, 2023

把Github当作数据库,搭建博客

Others3.0 min to read

网上有很多种搭建博客的方法,有前后台一把梭的,有静态网页的,也有大佬喜欢直接在Github的Issues上写文章。

今天给大家分享一种很方便的方法来搭建博客,无需服务器,前端可以是任意的技术栈。

可以实现的功能:

  1. 前端页面自定义
  2. 带评论系统
  3. 文章可以带标签分类
  4. 数据、图片保存在Github,长期储存
  5. CDN加速
  6. 自定义域名

当然,这种方式还是需要自己动手,并不是现成的一套技术。

最后的效果可以看我的博客Github仓库

如何实现

其实原理说出来很简单,因为Github有提供API接口的,可以访问Issues,而我们只需要通过Issues的接口来请求文章数据,每一篇文章对应一个Issue,每一个Issue的评论功能对应该文章的评论系统。

图片可以存储在当前仓库的另一个分支,用免费的jsdelivr来作CDN。

Github Page和一些Serverless提供商如vercel都可以修改自定义域名。

创建仓库和Token

需要在Github上新建一个仓库,然后申请一个Github Token,申请方式见官方文档

这个Token需要保存好,不能传到仓库的,可以用.env.local这种方式来储存和读取。

读取博文列表

博文列表也就是Github Issues,官方提供了2种方式来获取,分别是REST APIGraphQL API,需要使用官方的请求库core.js。我是使用的GraphQL API,因为它可以提前过滤不要的数据。

比如我想要请求的Issues列表是仓库zhangyu1818/blog,拥有者为zhangyu1818,仓库名为blog,它对应的GrpahQL请求如下:

{
  repository(owner: "zhangyu1818", name: "blog") {
    issues(
      states: CLOSED
      first: 100
      orderBy: { field: CREATED_AT, direction: DESC }
      filterBy: { createdBy: "zhangyu1818" }
    ) {
      nodes {
        number
        title
        createdAt
        updatedAt
        labels(first: 5) {
          nodes {
            color
            name
          }
        }
      }
      pageInfo {
        hasNextPage
        endCursor
      }
      totalCount
    }
  }
}

这一串数据请求了由zhangyu1818创建前100个关闭的Issue,每一个Issue请求前5个label标签,每一个Issue包含number、title、craetedAt等数据。

对应的REST API请求的方式和示例见文档

请求文章详情

每一个Issue都是一个数字,用数字请求指定的Issue可以得到里面的详情。

query queryIssueByNumber($number: Int!) {
  repository(owner: "zhangyu1818", name: "blog") {
    issue(number: $number) {
      number
      title
      url
      createdAt
      bodyHTML
      labels(first:5) {
        nodes{
          color
          name
        }
      }
    }
  }
}

Github API不仅可以请求Markdown的内容,也可以直接请求由Github渲染好的的内容HTML,这样我们连本地的Markdown渲染都可以省去。

对应的REST API请求的方式和示例见文档

评论系统

评论系统是有很多现成的轮子,这里推荐使用gitalk,使用方式见文档

需要先在Github创建一个应用,我的应用信息如下。

image-20210408191220681

使用方式

const gitalk = new Gitalk({
  clientID: "GITHUB_CLIENT_ID", // 你的应用id
  clientSecret: "GITHUB_CLIENT_SECRET", // 你的应用secret
  repo: "blog", // 你的仓库
  owner: "zhangyu1818", // 你的github名字
  admin: ["zhangyu1818"], // 你的github名字
  number: 1, // 需要issueNumber相同
})

gitalk.render('gitalk-container') // 渲染的元素

图片储存在Github

这个也是现有工具就能实现的功能,图形化工具PicGO,它也有命令行工具PicGo-Core,它同样需要使用Github Token,可以是之前申请的Token,也可以重新申请一个。

具体配置可以看参考教程

我配置的是将图片存在仓库的另一个分支。

image-20210408192506499

这样配置的话如果需要使用jsdelivr作CDN加速,配置的地址应该是

https://cdn.jsdelivr.net/gh/zhangyu1818/blog@files

页面的部署方式

部署方式推荐使用vercel,它可以很简单的配置在Github的主分支更新后自动的拉取和部署,同时支持很多种不同的前端技术栈,Vue和Angular都支持的,可以看这里

所以前端可以用任意的技术栈,我选择的是Next.js,然后再通过vercel来部署。

vercel部署的还有一个好处是可以在页面上配置一些环境变量,比如我们的Github Token,聊天的Client ID,同时也可以修改自定义的域名。

image-20210408193426232

配置好后代码里可以直接这样写。

const gitalk = new Gitalk({
  clientID: process.env.NEXT_PUBLIC_GITHUB_CLIENT_ID,
  clientSecret: process.env.NEXT_PUBLIC_GITHUB_CLIENT_SECRET,
  // ...
})

sitemap如何实现

如果是静态页面,可以需要在build之前先请求列表,再写一个sitemap.xml到本地,如果是服务端渲染,可以直接写一个API接口。

总结

这个博客我也用了挺久了,总的来说非常方便,是我折腾博客多年来说最好的一个方式,不需要本地储存数据,也不需要后台,也不需要买服务器来部署,Github上和网页就是一个镜像,需要改文章内容或者是标签,只需要在Github上改一下就行了。

唯一的缺点就是需要自己折腾折腾,对于爱动手的小伙伴来说,我觉得这种方式的自由度是很高的了。