跳到主要内容
全部文章

从零用 Astro 搭建一个极简博客

记录本站的搭建过程:技术选型、内容集合、构建期搜索与部署到 Cloudflare 的思路。

发布于 更新于 3 分钟阅读
《从零用 Astro 搭建一个极简博客》封面图
目录

我想要的博客很简单:写 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
---

新增文章不需要改任何路由代码——文件放进去,构建时页面自己长出来。

构建期搜索

站内搜索不想依赖外部服务,思路是构建期生成索引,浏览器端查询:

  1. 构建时把每篇文章转成纯文本(剥离 Markdown 标记,保留正文与代码);
  2. 输出一个精简的 search-index.json,正文截断控制体积;
  3. 搜索页首次输入时按需 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,剩下的交给构建。下一篇见。