从零用 Astro 搭建一个极简博客
记录本站的搭建过程:技术选型、内容集合、构建期搜索与部署到 Cloudflare 的思路。
发布于
更新于
3 分钟阅读
目录
我想要的博客很简单:写 Markdown,按下发布,页面立刻就在那里——没有后台、没有数据库、没有插件更新提醒。这篇文章记录本站的完整搭建过程,供想复制这条路的人参考。
为什么选 Astro
把候选摆出来对比一下:
| 方案 | 上手成本 | 默认输出 | 适合我吗 |
|---|---|---|---|
| Next.js | 中 | 需要服务端或复杂配置 | 杀鸡用牛刀 |
| Hugo | 低 | 静态 | 模板语言不合口味 |
| Astro | 低 | 零 JS 静态页 | ✅ 内容优先 |
Astro 的「孤岛架构」对我这种站点几乎是量身定做:默认输出零 JavaScript 的静态 HTML,需要交互的地方(主题切换、搜索、复制按钮)再用原生 <script> 加一小段代码。
内容即文章:Content Collections
Astro 的 Content Collections 让文章有了 Schema 校验。定义好 frontmatter 结构后,少写字段会直接构建失败,而不是悄悄渲染出残缺页面:
// src/content.config.ts(节选)
const blog = defineCollection({
loader: glob({ pattern: '**/*.{md,mdx}', base: './src/content/blog' }),
schema: z.object({
title: z.string().min(1),
description: z.string().min(1),
pubDate: z.coerce.date(),
slug: z.string().min(1),
category: z.string().min(1),
tags: z.array(z.string()).default([]),
draft: z.boolean().default(false),
}),
});
每篇文章只需要一个 Markdown 文件,加上这样一段 frontmatter:
---
title: '文章标题'
description: '一句话描述'
pubDate: 2026-11-12
slug: 'post-slug'
category: '技术'
tags:
- Astro
draft: false
---
新增文章不需要改任何路由代码——文件放进去,构建时页面自己长出来。
构建期搜索
站内搜索不想依赖外部服务,思路是构建期生成索引,浏览器端查询:
- 构建时把每篇文章转成纯文本(剥离 Markdown 标记,保留正文与代码);
- 输出一个精简的
search-index.json,正文截断控制体积; - 搜索页首次输入时按需
fetch索引,本地打分排序。
检索逻辑大约一百行,支持多关键词 AND 匹配,标题命中权重最高:
let termScore = 0;
if (title.includes(term)) termScore += 60;
if (tags.includes(term)) termScore += 20;
if (description.includes(term)) termScore += 25;
if (text.includes(term)) termScore += Math.min(hits * 6, 36);
实测 6 篇文章的索引只有几十 KB,就算以后到几百篇,也仍然比一张普通图片小。
代码高亮与复制
代码高亮由 Shiki 负责,Astro 内置。双主题配置一次搞定:
// astro.config.mjs(节选)
markdown: {
shikiConfig: {
themes: { light: 'github-light', dark: 'github-dark' },
},
},
复制按钮则是十几行原生脚本:给每个 pre 套一层带语言标签的容器,点击时写入剪贴板。
部署
构建产物是纯静态文件,扔给 Cloudflare Pages 即可;健康检查之类的动态接口留给独立的 Workers,两边互不拖累。首版刻意不接 SSR——一个内容站,静态就是最快的架构。
写在最后
整套下来的感受:约束越少的东西,越容易坚持。写文章的唯一流程就是 git commit,剩下的交给构建。下一篇见。