我是如何一步步把这个博客搭建起来的
好久不见!经过许久的折腾以后,终于闲下功夫来复盘一下博客如何部署起来的了!话不多说,这就进入主题!
选择博客主题和架构
作为一个主要承担内容输出的部分,我首先在自行开发和成熟博客框架上进行了趋于中间化的选择。成熟的框架,如 WordPress,固然可以完整提供博客所具有的全部功能,但是略显笨重,且对于本来空间就不大的云服务器更是一种考验。如果全部自己撰写的话,又会陷入到维护成本过高的问题。各种小部件的适配和样式的维护,都是一件很痛苦的事情。由此看来,静态博客生成器是一个不错的选择。
GitHub 上有很多成熟的静态博客生成器,如 Hexo、Jekyll、Hugo 等等。进行了一番对比后,我最终选择了 Hexo 和 Hexo-next 主题。Hexo 本体是基于 Node.js 的,我可以专心使用 Markdown 书写内容,而由一些 hexo 终端命令来渲染成所需的静态文档。而且,经过对一些 GitHub 仓库的浏览,我发现 Hexo 的主题和插件也是非常丰富的,可以满足我对于博客的基本需求。
主题安装与配置
Hexo 的文档很清楚,我可以直接通过 npm 命令来安装 Hexo 本体,并安装 Hexo next 主题:
1 | npm install hexo-cli -g |
安装完成后,博客根目录下会出现两种 yml 配置文件,一个是_config.yml
,称为 Hexo 配置文件;一个是_config.next.yml
,称为主题配置文件。接下来就需要对这两个文件进行深一步配置。
Hexo 配置文件的进一步配置
首先是基本信息的填写,如博客标题、副标题、描述、关键词、作者、语言、时区等等。所有这些配置都将写入 HTML 的 meta
标签中,以便搜索引擎更好的索引博客。
1 | title: '随心记' # 标题 |
我们安装的主题是 hexo next 主题,要在主配置文件(_config.yml
)中写入主题的名称:
1 | theme: next |
以上步骤结束,我们就可以通过 hexo s
命令来启动本地服务器,通过 localhost:4000
来预览博客的样子了。但是,我们还需要对主题配置文件进行进一步配置。
next 主题配置文件的进一步配置
官方配置文档在这里,可供参考
我所安装的 Hexo 已经是 5.0 版本以后了,官方推荐使用替代配置文件_config.next.yml
来进行主题配置,以防止更新时被覆盖。
首先是博客主题(scheme),NexT 提供了 4 种主题(Muse
、Mist
、Pisces
和 Gemini
),我直接选择了默认主题 Muse
,可能我个人对这个也没啥大要求吧,哪天可以改改试试其他的。
1 | scheme: Muse |
然后是暗黑模式,这可以通过 darkmode
来设置。我并没有改变这个选项,感觉这个主题应该还是提供一个按钮,供用户切换比较好。
1 | darkmode: true |
接下来是站点 Favicon,是浏览器标签页上会显示的小图标,需要在 favicon
下进行设置,并引用相关图片资源文件。目前本站还没有进行这样的设置,以后会加上。
1 | favicon: |
有关博客文章的版权声明,鉴于本博客大多以分享为主,我沿用了主题提供的 CC4.0 配置,意味着放开了共享和演绎(虽然我的文章一般没啥人看就是了 qwq)。这个选项的配置效果决定了文章底部的版权声明显示。
1 | creative_commons: |
为了优化 SEO,OpenGraph 当然是必须配置的。这里参考 hexo 的配置文档配置了一些项目。
1 | open_graph: |
目录设置需要在 menu
选项下进行配置,其配置分为 Key
、link
和 icon
三部分。其中:
Key
是目录项的名称,大小写敏感。除了home
和archive
以外,其他类型都需要在source
文件夹下手动创建文件夹和对应的index.md
文件link
是目录项的链接,是链接到本站的相对路径,在实际测试时发现也可以写站外的绝对路径icon
是目录项的 Font Awesome 图标名,可以在这里找到link
和icon
之间用||
分隔
1 | menu: |
menu
下还可以配置 sub-menu
,其配置和 menu
类似,但是本站没必要配置这个,就不写了。
另外,在 menu_settings
还可以配置使用 badges
或者 icons
。badges: true
会显示文章、类别和标签的数量。默认的 icons: true
会在 menu
项前显示图标。
侧边栏
博客中难免需要显示一些个人相关的社交平台联系链接。这些链接可以通过 social
配置项进行配置。它的格式与上述 menu 类似,但是指定的链接必须是绝对链接。
1 | social: |
通过 social_icons
配置项可以进行进一步配置,如是否启用(enabled
)、是否只显示图标不显示描述(icons_only
)、是否显示过渡动画(transition
)等。
中国常见的社交平台对应的 Fontawesome 图标名称总结如下:
社交平台名称 | Fontawesome 图标名称 |
---|---|
知乎 | fab fa-zhihu |
微博 | fab fa-weibo |
微信 | fab fa-weixin |
fab fa-qq | |
抖音 | fab fa-douyin |
人人 | fab fa-renren |
B 站 | fab fa-bilibili |
对于单个博客文章,Table of Contents(TOC)
是非常必要的,它可以显示你的文章的大致结构。可以通过 toc
配置项进行启用和禁用。我的配置如下:
1 | toc: |
侧边栏所展现的个人头像可以通过 avatar
来进行配置,NexT 主题还支持使用 rounded
属性设置圆形头像,rotated
属性支持鼠标悬停时旋转头像。
页脚
以下配置需要在 footer
选项下进行配置。
备案信息
众所周知,开在中国大陆的站点都需要备案,而备案信息是需要在页脚显示的。这里可以通过 beian
配置项进行配置,如下:
1 | beian: |
建站时间
一般建站的时候,总会往页脚加入开站时间,类似于 2020-2023
这样的。默认情况下,NexT 主题会显示当前年份,可以通过 since
配置项手动显示建站起始时间。
1 | footer: |
页脚图标
页脚图标会显示在年份和版权信息之间,往往是一个红心图标。可以通过 icon
选项做更多自定义配置,如修改图标名称、修改图标颜色、使图标动起来等。
版权信息
版权信息显示在页脚图标右侧,由 copyright
配置中的内容指定,如果未指定,则使用 Hexo 配置文件中的 author
配置项。
生成平台信息
在默认情况下,NexT 主题会在页脚显示 Powered by Hexo & Next.xxx
,表示生成器和主题,可以通过 powered
配置项进行更改。我觉得留着也没什么问题,就没改。
域名配置
根据 GitHub 相关配置文档和 Hexo 文档,需要在项目根目录下创建一个 CNAME
文件,里面写入你的域名,如 example.com
。由于 hexo 部署时相当于把整个 source 文件夹复制到一个新的分支,故这个 CNAME
文件需要创建在 source/
文件夹下 [1]。
在 Hexo 侧,需要在主配置文件_config.yml
中配合作这样的设置,以正确加载脚本及相关资源文件:
1 | url: https://blog.jason0743.space/ |
其中 URL 项需要填写自己的自定义网址。我是使用了 blog 作为三级域名,所以在 URL 处填写的是整个网址,后面以斜杠 /
为结尾,而 root 就是网页的根目录。
如果今后需要将博客部署在子目录中(像 https://example.com/child/
这样),就需要在 url 中带上子目录,在 root 项填写带有两边斜杠的子目录名(对于 https://example.com/child/
这里就需要设置为 /child/
)。
现代网页的地址末尾已经不一定需要 html 后缀了,甚至,主页的 index
字样我们也可以不需要(虽然实际上 Hexo 还是生成了它)。把这两个配置为 false
即可做到这一点。
1 | pretty_urls: |
启用资源文件夹
我的博客项目中会有很多图片,把它们都放在 source/images
文件夹中则会显得非常拥挤且不好管理。Hexo 提供了一种资源文件夹的概念,它可以在创建的新文章同级目录自动创建一个同名文件夹,然后使用相对路径插件来引入这些资源。
在主配置文件 _config.yml
中,将这个选项设为 true
即可启用该功能。
1 | post_asset_folder: true |
撰写文章时,使用这个语法插入即可,其中 slug 处要填写文件名:
1 | {% asset_path slug %} |
安装插件
评论显示
静态站并没有 “后端” 这个概念,传统的评论系统该怎么实现呢?我们可以借助一些插件来实现。
我在这里的选择是 Waline,比起之前的 Valine 来说,更加安全 [2],但配置起来需要一定时间。它需要同时考虑到 server 和 client 的部署问题。
Waline 官方提供了部署文档,所有步骤跟随这个走就行。
服务端配置
LeanCloud 注册当然要选国际版,懂得都懂~
首先是 LeanCloud 端数据库的配置,注册账号和创建应用的过程就不赘述了(作为普通白嫖用户当然要选择开发版),然后到左侧的设置→应用凭证中,记下 AppID、AppKey 和 MasterKey,以后要用到。
接下来使用 Vercel 进行服务端部署,如果没有账户的话,可以直接使用 GitHub 账号登录。然后点击 Waline 文档中的 Vercel 部署按钮或直接访问这个仓库的 README.md 文件。
接下来会基于一个简单的模板创建 Git 仓库,作为 GitHub 常驻用户肯定时要选择 GitHub 的,如果有别的平台也可以点击别的平台按钮创建。
项目创建成功后,进入到控制台中,从上方的 “Settings” 中进入项目设置,然后点击左侧的 “Environment Variables”,进入环境变量配置,建立三个环境变量 LEAN_ID
、LEAN_KEY
、LEAN_MASTER_KEY
,分别对应上一步在 LeanCloud 获得的 AppID、AppKey 和 MasterKey。
然后点击顶部的 “Deployments” 进入部署页面,选择最近一次部署,点击 “Redeploy“使得刚才的环境变量生效。部署好后就可以回到主页点击”Visit“访问服务端了。
其界面大致是这样的
如果需要加入域名(vercel 默认域名实在有些丑),则依然需要进入设置页中,这次需要进入”Domains” 中,输入需要绑定的域名并点击 “Add” 添加域名,然后在服务商处加入 CNAME 解析记录,其值为 cname.vercel-dns.com
,之后就可以用自己的域名来访问评论系统和管理端了。
立即访问管理端(<url>/ui/register
)进行注册,注册成功后,以后就可以通过 <url>/ui
管理评论了。
这里最好通过账号绑定设置(<url>/ui/profile
)到自己常用账户上,防止忘记登录凭证。
<url>
为 vercel 域名设置中所列出的域名,项目新建的默认值一般为 <project-name>.vercel.app
客户端配置
客户端需要进行样式导入和代码注入,对于 hexo-next 来说,像下面这样安装插件并加以配置即可。
1 | npm install @waline/hexo-next |
然后在主题配置文件 _config.next.yml
中加入以下内容:
1 | waline: |
首先当然要启用该插件(enable:true
)。然后需要设置 serverURL
为刚才部署的服务端地址,如果使用了自定义域名的话,这里就需要填写自定义域名。语言当然设置为 zh-CN
,我也启用了 pageview
和 commentCount
两个功能,显示文章的阅读统计和评论数量,配置效果如下:
视频 / 音乐嵌入
博客如果只有静态的文字和图片的话,也未免太单调了吧!如果能适时地嵌入一些其他网站或自己上传的资源,就更好了。我选择的是 mmedia 插件,因为它目前支持较广,而且使用也比较方便。
针对 hexo,只需要安装 hexo-tag-mmedia 插件即可,安装方法如下:
1 | npm install hexo-tag-mmedia --save |
然后在 _config.yml
下采用作者推荐的默认设置即可:
1 | mmedia: |
在使用上,假如要嵌入一个 B 站的视频,只需要使用这个简单语法:
1 | {% mmedia "bilibili" "bvid:BV<xxxxx>" %} |
即可,其中第一个参数是要引用的视频网站名称,第二个参数是要引用的视频 id,以冒号或者等号分隔都可以。
如果要嵌入音乐播放列表,则需要采用其中的 MetingJS 标签形式,采用的参数可以在这里了解。
1 | {% mmedia "meting" "server=<netease|tencent|kugou|xiami|baidu>" "type=<song|playlist|album|search|artist>" %} |
其支持的平台其实已经能够涵盖常见的用途了。如果以上几种不够用,还有最后的 Audio 和 Video 参数打底,它可以支持上传自有资源,插入原生的标签。
不过这个插件的原作者说他要弃坑了,保证稳定性的话,还是最好找个替代品,或者自己二次封装一下比较合适。
Markdown 渲染器配置
Hexo 默认搭配的渲染器是 hexo-renderer-marked
,其支持的渲染格式有限,所以我重新使用了 hexo-renderer-markdown-it
,它支持更多的解析和渲染格式,如 GFM 和 Commonmark 等,还支持插件。
在安装它之前,需要卸载 Hexo 默认自带的渲染器。
1 | npm uninstall hexo-renderer-marked --save |
然后再安装 hexo-renderer-markdown-it
。
1 | npm install hexo-renderer-markdown-it --save |
它的配置在 _config.yml
中,直接使用默认的简单配置即可。
1 | markdown: |
其实我最需要的是脚注(markdown-it-footnote
)功能,这个语法可以用来写一些参考文献,或者是一些引用的资料。
部署到 GitHub
由于将博客放到云服务器上操作过程过于繁琐(万一域名失效了还得四处拷贝搬运,并且配置域名 HTTPS 啥的也是不少麻烦),我选择使用 GitHub Pages 功能来托管我的内容。GitHub Pages 是 GitHub 提供的一个静态网页托管服务,可以将静态网页托管到 GitHub 上,然后通过 username.github.io
的形式来访问。这样做的好处是,我可以将博客的源码和静态网页内容分开,而且可以通过 GitHub Actions 来实现自动化部署。
建立仓库
在 GitHub 上建立一个新的仓库,并做好初始化,稍后我们会将博客的源码推送到这个仓库上。
本地的博客文件夹中,现在应该已经是这样的结构:
1 | +--+ |
在这个文件夹下运行 git init
,之后再把这个分支推送到仓库中。
目前,我的博客全部源码内容都在 main
分支上,而博客的静态网页内容则在 gh-pages
分支上。这样做的好处是,我可以在 main
分支上进行博客的编辑和维护,而 gh-pages
分支则可以作为一个单独的静态网页仓库,用于部署到 GitHub Pages 上。
使用 GitHub Actions 全自动化部署过程
Hexo 本身其实也有提供 deploy 命令用于部署仓库,但是这个命令每次都要手动执行,稍微有点不太方便。故我选择了尝试使用 GitHub Actions 来实现自动化部署。
GitHub Actions 是处于 git 仓库中 .github/workflows
文件夹下的一个 yml 配置文件。其记载了在什么样的条件下,自动执行什么样的操作。
我们的文件是这样的:
1 | name: publish-webpage |
注意,这些代码与 hexo 文档上的部署代码并不一样,主要的不同点在于官方教程使用了 actions-gh-pages
,而自己这边使用的是 git 原生命令来自己建一个部署密钥。
其实个人认为官方这个代码是比较好的,因为其所使用的 actions-gh-pages
无需担心部署密钥,github_token
是可以自动在工作流中认证的,不是个人访问令牌,除了首次部署外,无需特别配置。
而且,它还注意了 npm 依赖的缓存,以后要是再次部署的话,无需再费很长时间安装依赖,博客上线速度可以大大加快。
生成 deploy key 的过程如下:
生成 Deploy key
-
在本地运行
ssh-keygen -t rsa -b 4096 -C "Hexo Deploy Key" -f github-deploy-key -N ""
生成一个新的密钥对。 -
在仓库的设置选项卡中,选择 “Secrets”(现为 “Secrets and variables”),新建名称为 “HEXO_DEPLOY_KEY”(这个名称是与刚才工作流配置文件中的
secrets.*
后面的内容是对应的)的密钥,将刚刚生成的公钥对应的私钥的内容复制进去。配置完成后,Action Secrets 列表(现 Actions Secrets and variables 中的 Repository secrets)中应该会出现一个新的密钥。
-
转到 “Deploy Keys” 中,右上角新添加一个部署密钥。
-
将刚才生成公钥的内容复制进去(以 ssh-rsa 开头),并勾选 “Allow write access”。
配置完成后,每次将博客源码推送到 main
分支时,GitHub Actions 就会自动执行部署操作。
保留 gh-pages 提交历史
上面的 Actions 是很容易想的,但每次提交仓库后,会发现 gh-pages 分支的提交历史都是一条直线,没有任何记录。这是因为 hexo-deployer-git
每次部署时,都会先清空 gh-pages 分支,再重新生成静态网页,再提交到 gh-pages 分支上。
干净提交也并不是不可以,但每次提交后,都会导致 gh-pages 分支的提交历史被重写,这样就无法通过提交历史来查看博客的更新记录了。
怎么办呢?这时需要去看看 hexo-deployer-git
的源码寻找答案。
1 | // setup() |
也就是说,hexo-deployer-git
会先在 .deploy_git
中生成仓库,并将它强制推送到 _config.yml
配置中的仓库上,如果文件夹不存在,则会进入初始化流程。
因此,我们要在 hexo deploy
之前,先手创建一个 .deploy_git
文件夹,并将当前的 gh-pages
分支的内容复制进去,这样就可以保留提交历史了。
可以使用 git clone 命令,也可以使用 actions/checkout
来实现在工作流中克隆仓库内容。
1 | jobs: |
使用正确的时区
在使用 GitHub Actions 生成博客时,会发现生成的时间与实际不太一致,因为运行我们的 Actions 的机器跟我们并不在同一时区。这可以通过设置时区来解决。
1 | env: |
访问优化
博客的内容会越来越多,大量的文章和图片难免会拖慢访问速度,hexo 及相关的插件也提供了一些优化的方法。
hexo-all-minifier
这个插件主要用于对博客中生成的 HTML、CSS、JS 和图片文件进行压缩,减少文件及仓库的体积,提高访问速度。
通过 npm 安装就可以使用:
1 | npm install hexo-all-minifier --save |
然后在 _config.yml
中设置
1 | all_minifier: true |
就可以开启插件。从实际使用体验来看,它自带的 js_concator、js_minifier、html_minifier、css_minifier 都可以保持开启,而在开发(撰写文章)时需要暂时关掉 image_minifier
,因为压缩图片比较费时。
cache
NexT 从 6.0.0 版本开始引入了内容生成缓存,顾名思义,在重复生成大量内容时这个选项可以节省下大量的时间。在 _config.next.yml
中完成这个配置即可:
1 | cache: |
查阅资料得知 waline 使用了 vercel 部署了一个 webapp,隔离了前端和存储,避免了安全问题 ↩︎