把博客迁到 Astro:一次彻底的重写

上一次换主题是三年前,那时候用的是现成的 PHP 博客程序,改一行样式要刷新三次页面。这次索性推倒重来:静态生成、内容写在 Markdown 里、样式全部自己写。
为什么是 Astro
最直接的原因是默认零 JavaScript。博客这种内容型站点,95% 的页面只需要 HTML 和 CSS,可大多数框架会先丢一个几百 KB 的运行时过来,然后才开始渲染正文。
Astro 的做法相反:组件在构建期跑完,产出的就是纯 HTML。需要交互的地方,用 <script> 单独挂一小段 JS——我整个站点加起来不到 8 KB。
| 方案 | 首屏 JS | 构建耗时 | 心智负担 |
|---|---|---|---|
| 传统 SPA | ~180 KB | 快 | 中 |
| SSR 框架 | ~60 KB | 中 | 中 |
| Astro 静态 | ~8 KB | 快 | 低 |
内容就是文件
内容用 Markdown 写,frontmatter 定义元信息:
---
title: 把博客迁到 Astro
date: 2026-10-26
tags: [Astro, 前端]
cover: /images/cover-1.svg
---
然后在 content.config.ts 里用 Zod 校验字段。写错一个字段名,构建直接报错——比在运行时悄悄渲染出空白页要好得多。
const posts = defineCollection({
loader: glob({ pattern: '**/*.md', base: './src/content/posts' }),
schema: z.object({
title: z.string(),
date: z.coerce.date(),
tags: z.array(z.string()).default([]),
}),
});
静态生成的真正好处不是「快」,而是确定性。同一份输入永远产出同一份输出,出问题的时候可以本地复现。
为什么不用 Tailwind
这不是反对 Tailwind,它在团队协作里确实高效。但这个站只有我一个人维护,而且我对想要的视觉效果有很具体的想法:Material Design 3 的色板、圆角梯度、两套主题下的阴影差异。
这些用工具类拼出来会变成一长串 shadow-[0_4px_12px_rgba(28,20,48,0.07)],改一次要全局搜索替换。写成 CSS 变量反而清爽:
:root {
--surface: #ffffff;
--outline: rgba(26, 24, 32, 0.09);
--r-lg: 28px;
--shadow-2: 0 4px 12px rgba(28, 20, 48, 0.07);
}
[data-theme='dark'] {
--surface: #1a1720;
--outline: rgba(236, 233, 243, 0.1);
}
切换主题只是改 document.documentElement.dataset.theme,所有颜色自动跟着变。颜色、圆角、阴影都是令牌,不是样式。
留下的三个坑
- 暗色模式闪白:主题必须在
<head>里同步读取 localStorage,不能等 JS 加载完再做,否则会闪一下。 - 中文字体:不要指望网络字体,直接堆系统字体栈,
PingFang SC和Microsoft YaHei覆盖 99% 的情况。 - 图片尺寸:封面统一 16:9 并显式写
width/height,避免布局抖动。
接下来
还差评论区和 RSS,另外想把「此刻」卡片接到真实的接口上,而不是手写死数据。
慢一点没关系,反正是自己的地方。