起因
今天花了几乎一整天,把博客框架从 Hexo 迁移到了 Astro。我的博客最开始是在 2019 搭建的,哪个时候 Hexo 还是比较流行的静态博客生成框架,NexT 主题也是 Hexo 框架中比较流行的主题。在那一年,可以看到很多使用 NexT 主题的博客,如今看到的就似乎比较少了。经过六年的前端技术发展,Hexo 多少还是显得有点落后了,并不是基于当前流行的 React、Tailwind CSS、TypeScript 这样的主流前端框架,定制一些页面对我这个前端新手着实存在不小的困难。
说起原来博客的页面,本身主题是基于 NexT。为了稍显一些个人博客的不同之处,当时硬编码 CSS,使用 Chrome Dev Console,参考 Twitter 的暗色主题,设计了一套暗色的 color scheme。但是如今再想让我去修改这些配置,完全就有心无力了。而且博客只有一种主题,虽然 NexT 支持配置亮色和暗色主题,但是并不支持动态切换,我又完全没有能力去修改博客框架,让其支持主题切换。
恰巧又有很多博客主,都有迁移到 Astro 的博文。大致浏览了 Astro 的文档,基本满足我的需求。Astro 本身也是基于主流的前端技术,我也在这段时间里,粗糙地学了一遍前端的主流技术,这次就选择了 Astro 作为新的博客框架,还是希望能够使用长久一些,不再折腾博客框架,安安心心写博客文章。
Astro Paper
选定了 Astro 作为博客框架后,我选择的博客主题是 AstroPaper。吸引我的主要是主题样式和使用的技术栈。AstroPaper 主题足够简洁,基本没有影响阅读的元素。
主要戳中我的是下面这些点:
- 主要技术栈
- Main Framework - Astro
- Type Checking - TypeScript
- Component Framework - ReactJS
- Styling - TailwindCSS
- 主要特性
- SEO-friendly
- light & dark mode
- fuzzy search
- sitemap & rss feed
- highly customizable
我使用的是 pnpm 包管理器,也可以参考官网文档,使用其他包管理器,使用下面的命令就可以创建一个 AstroPaper 主题的博客:
pnpm dlx create-astro --template satnaing/astro-paper
更新:
过了一段时间之后,我发现上面这条命令也是 clone 的主题的官方仓库,考虑到后续同步上游的更新,我做了修改。 更换成了 fork 原仓库,在 blog 分支修改配置我的个人博客。
博客基础配置
网站的相关配置,就直接配置在 config.ts
就可以了。参考原有 Hexo 配置,手动配置新的配置文件。
如果不需要迁移博客,那么简单配置下,其实就已经可以使用,我则需要把历史的 Hexo 博客的重要配置迁移到 Astro Paper 上,以下是一些记录。
迁移
博客文章迁移
Astro 的博客文章虽然和 Hexo 一样,都是 Markdown 语法,但是一些元数据方面的设置不太一样。
- date -> pubDatetime
- update -> modDatetime
--- <!-- more -->
之间的数据,转换成 description- mathjax,categories 在 Astro 中属于无效标签,需要移除
于是最开始的任务就是编写脚本,将历史数据转换内容到新的数据格式。最近也一直在尝试 AI 编程,Deepseek 的服务最近又一直不太稳定,没办法使用 vscode + deepseek api + cline 编程,就尝试了字节的 Trae,毕竟可以免费使用 Claude-3.5-Sonnet
,效果非常 nice。脚本放在了这里,以及使用说明。
LaTeX 数学公式支持
基本参考官方文档操作, Adding LaTeX Equations in AstroPaper blog posts | AstroPaper
- Install the necessary remark and rehype plugins
pnpm install rehype-katex remark-math katex
- 编辑
astro.config.ts
// other imports
import remarkMath from "remark-math";
import rehypeKatex from "rehype-katex";
export default defineConfig({
// other configs
markdown: {
remarkPlugins: [
remarkMath,
remarkToc,
[
remarkCollapse,
{
test: "Table of contents",
},
],
],
rehypePlugins: [rehypeKatex],
// other markdown configs
},
// other configs
});
- 编辑
src/layouts/Layout.astro
---
import { LOCALE, SITE } from "@config";
// astro code
---
<!doctype html>
<!-- others... -->
<script is:inline src="/toggle-theme.js"></script>
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/katex.min.css"
/>
<body>
<slot />
</body>
不过行间公式在暗色模式下存在渲染错误,在 issue 区看到其他人也存在同样的问题,但是没能解决。我现在使用数据公式比较少,就暂时搁置不处理了。
更新:尝试一翻之后,我找到了解决方案,放在了 issue 区。
历史博客文章路径兼容
原本 hexo 的路径引用是 blog.guanglai.me/post-name
,在 AstroPaper 主题中的文章路径是 blog.guanglai.me/posts/post-name
,于是想到了下面两种解决方案。
第一种方案
修改 astro 的文章路径,保持一致
posts
下的文件放到上级目录pages
下,删除index.astro
。- 修改其他页面的路径引用路由,/posts/${slug}/,删除 /posts
Posts.astro
TagPosts.astro
第二种方案
使用 Astro 提供的重定向功能,将原来的博客地址,重定向到新的博客地址。这是 Astro 的路由文档 Routing | Docs,修改 astro.config.ts
就可以定义静态路由重定向。于是同样编写了脚本,将原有的 /post-name
全部重定向到 /posts/post-name
,脚本放在这里。
// astro.config.ts
import { defineConfig } from 'astro/config';
export default defineConfig({
redirects: {
'/old-page': '/new-page',
'/blog': 'https://example.com/blog'
}
});
文章目录
当时看到了这篇文章 再见 Hexo,你好 Astro! | 4Ark, 参考博主的配置,实现了大屏幕下的目录展示。具体修改直接参考博客的 commit 即可。
sitemap、rotbots.txt 和 RSS
AstroPaper 会自动生成需要的文件,但是使用 pnpm dev
开发阶段不会生成下面这些文件,pnpm build
构建最终产物才会生成。本地可以使用 pnpm preview
在构建好后预览。
- sitemap.xml (主题是分块 sitemap.xml,只有:sitemap-index.xml 和 sitemap-0.xml)
- rss.xml
- robots.txt
GitHub Page 自定义域名
CNAME 文件配置在 public
目录下,用于 GitHub 自定义域名。
文件内容
blog.guanglai.me
OG 图片
AstroPaper 支持生成 OG 图片,但是原有的主题字体默认只支持 Latin
字符,对于非 Latin
字符的博客,需要自定义加载相关字体。
我加载了以下字体,后续看是否需要减少一些:
// file: loadGoogleFont.ts
async function loadGoogleFonts(
text: string
): Promise<
Array<{ name: string; data: ArrayBuffer; weight: number; style: string }>
> {
const fontsConfig = [
{
name: "Noto Sans CJK JP", // 日文字体
font: "Noto+Sans+JP", // Google Fonts 中的名称
weight: 400,
style: "normal",
},
{
name: "Noto Sans CJK JP",
font: "Noto+Sans+JP:wght@700", // 加粗版本
weight: 700,
style: "normal",
},
{
name: "Noto Sans CJK SC", // 简体中文字体
font: "Noto+Sans+SC", // Google Fonts 中的名称
weight: 400,
style: "normal",
},
{
name: "Noto Sans CJK SC",
font: "Noto+Sans+SC:wght@700", // 加粗版本
weight: 700,
style: "normal",
},
{
name: "Noto Sans CJK TC", // 繁体中文字体
font: "Noto+Sans+TC", // Google Fonts 中的名称
weight: 400,
style: "normal",
},
{
name: "Noto Sans CJK TC",
font: "Noto+Sans+TC:wght@700", // 加粗版本
weight: 700,
style: "normal",
},
];
// other codes
}
facicon 图标
原有在 Hexo 上使用的图标格式是 png
和 ico
,并且内容是动漫截图,其实也没有特别的含义,只是我曾经使用过的头像之一。于是这次就一起换了图标。
- 使用 https://formito.com/tools/favicon 生成
- font: ZCOOL QingKe HuangYou
- backgroud color: 2F3742
- 放在
public
下,命名为favicon.svg
即可 - 删除了一些不需要的资源
部署到 GitHub Page
Astro 官方有部署到 GitHub Page 的指导,提供了但是官方文件是源文件和网站在同一个 GitHub 仓库,我则是把源文件仓库设为私有,需要部署到目标仓库。经过了一翻调研,也就不使用官方部署指南提供的 GitHub Action 配置了。
在 .github/workflows
下,新建文件 deploy.yml
,文件内容如下:
name: GitHub Pages
on:
push:
branches:
- main
pull_request:
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
contents: write
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
run_install: false
- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'
- name: Install dependencies
run: pnpm install
- name: Build
run: pnpm build
- name: Deploy
uses: peaceiris/actions-gh-pages@v4
with:
deploy_key: ${{ secrets.TARGET_REPO_DEPLOY_KEY }} # targert repository deploy key secret
external_repository: knothhe/knothhe.github.io
publish_dir: ./dist
publish_branch: master # default: gh-pages
使用 peaceiris/actions-gh-pages@v4
的 deploy key 的方式推送的目标仓库,所以需要在目标仓库和源仓库配置 DEPLOY_KEY 的公钥和私钥。
步骤参考:
- 本地生成 ssh 公钥和私钥,不带 passphare。
ssh-keygen -C "github@action"
- 目标仓库配置公钥
- 依次点击
Settings > Deploy keys > Add deplay key
配置设置 - 生成的公钥,即带有
.pub
后缀的文件的内容复制到文本框中
- 依次点击
- 源仓库配置私钥
- 依次点击
Settings > Secrets and variables > Actions > New repository secret
配置设置 - 生成的公钥,即不带有
.pub
后缀的文件的内容复制到文本框中
- 依次点击
Google Site Verification
官方推荐是使用 .env
配置,但是 .gitignore
文件里,忽略了 .env
文件,所以考虑本地生成时,可以配置 .env
文件,使用 GitHub 时,将内容配置到 GitHub 仓库中。
# in your environment variable file (.env)
PUBLIC_GOOGLE_SITE_VERIFICATION=your-google-site-verification-value
采用密钥配合 GitHub Action 方式配置
- GitHub 仓库配置,同样是在源仓库的
Settings > Secrets and variables > Actions > New repository secret
下配置,名称为GOOGLE_SITE_VERIFICATION_SECRET
,值配置为 Google Search Console 给的值。 - GitHub Action 中在
checkout
之后添加下面的配置:
- name: Create .env file
run: |
echo "PUBLIC_GOOGLE_SITE_VERIFICATION=${{ secrets.GOOGLE_SITE_VERIFICATION_SECRET }}" >> .env
评论
采用 giscus,参考 AstroPaper 官方集成 Giscus 的文章。
后记
本次折腾基本就是做了上面这些步骤,花费了几乎一天的时间。