主题
重构这个站点时,判断标准只有一条:能不能在构建期做完的事,就不要留到运行期。
GitHub Pages 是纯静态托管,没有服务端。这个约束让选择变清楚,而不是变穷。
案例
Astro 6 去掉了约定式内容集合。旧代码里的 post.slug 和 post.render() 一起失效。迁移不是换个配置文件名,是条目标识和渲染 API 两处一起断。
同时,标题如果继续吃系统字体,同一篇文章在 macOS 和 Windows 上是两种气质。外链 Google Fonts 能统一,但首屏会多一个第三方域名。
这两件事都发生在「站点已经能发文章」之后。该补的是构建期能力,不是运行时花活。
观点
GitHub 文档把 Pages 定义成静态托管,并写明不跑 PHP、Ruby、Python 这类服务端语言。静态托管上,高级感来自敢删:Server Islands 做不了,全站搜索在文章很少时不值得,评论要引入第三方脚本。留下的四件事——内容层、字体、分发出口、OG 图——都必须在 astro build 里结束。
内容主线已经在Markdown 那篇锁死。这篇只谈工程层怎么把那条主线托住。
实操
内容层改显式 loader
配置从 src/content/config.ts 搬到 src/content.config.ts,范围用 glob() 写死:
import { defineCollection, z } from 'astro:content';import { glob } from 'astro/loaders';
const posts = defineCollection({ loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/posts' }), schema: z.object({ title: z.string(), pubDate: z.date(), tags: z.array(z.string()).default([]), draft: z.boolean().default(false), }),});
export const collections = { posts };迁移时真正会踩的两处:post.slug 改成 post.id;渲染从实例方法变成顶层 render()。headings 顺手就是右侧目录,不必自己解析 HTML。
字体自托管
fonts: [ { provider: fontProviders.google(), name: 'Newsreader', cssVariable: '--font-display-latin', subsets: ['latin'], },]构建期下载并生成 @font-face。中文按 unicode-range 切片,浏览器只取当前页用到的那几块。
四个出口一次齐
- RSS:
/rss.xml - sitemap:给爬虫
- JSON-LD:告诉搜索引擎这是
BlogPosting - OG 图:构建期用 satori + resvg 画,中文按标题字符取子集,不要整包 CJK
npm i satori @resvg/resvg-js总结
有些能力明确不做:
| 能力 | 结论 |
|---|---|
| Server Islands | 静态托管没有服务端,做不了 |
| 全站搜索 | 文章少时用不上,等内容够了再说 |
| 评论系统 | 引入第三方脚本的代价大于收益 |
工程上大部分「高级感」不来自加了什么,而来自敢删掉什么。
写作本身怎么避免每篇从零发明,见把写博客做成一个 skill。
参考
- What is GitHub Pages?(查阅 2026-09-14)— Pages 是静态托管;文档写明不支持 PHP / Ruby / Python 这类服务端语言。




