用Astro搭建静态博客:从内容集合开始到部署
把博客做成纯静态站点,内容用Markdown维护,构建产物丢到任意静态托管。记录选型理由、内容集合写法与上线前的检查清单。
个人技术博客最容易踩的坑不是选不出框架,而是把内容管理做重了:数据库、后台、登录、编辑器插件,最后文章没写几篇,维护后台倒成了负担。
为什么是静态生成
技术博客的读写比极端失衡:一个人写,很多人读,且内容几乎不变。这种场景下最合理的架构是构建时把数据全部算好,运行时只返回HTML文件。
带来的好处很直接:
- 没有应用服务器和数据库连接,托管成本几乎为零,随便一台Nginx或对象存储都能放;
- 首屏不需要等待接口返回,TTFB和LCP稳定,对SEO友好;
- 内容就是仓库里的
.md文件,备份、回滚、版本对比都用Git,不需要额外的内容管理后台。
代价是每次更新都要重新构建,以及动态功能(评论、搜索)得另想办法。前者对个人博客完全无所谓,后者可以用客户端索引和独立的小API解决。
内容集合定义元数据
Astro的内容层用glob()把目录里的Markdown加载成集合,再用Zod约束frontmatter。字段写错会在构建阶段直接报错,比上线后才发现日期格式不对强得多。
import { defineCollection, z } from 'astro:content';
import { glob } from 'astro/loaders';
const posts = defineCollection({
loader: glob({ base: './src/content/posts', pattern: '**/*.md' }),
schema: z.object({
title: z.string().min(1),
description: z.string().min(1),
pubDate: z.coerce.date(),
category: z.string().default('未分类'),
tags: z.array(z.string()).default([]),
draft: z.boolean().default(false),
}),
});
export const collections = { posts };
一个容易忽略的细节:YAML里的
pubDate: 2026-11-02会被解析成UTC午夜。格式化时一律用getUTCFullYear()这类UTC取值方法,否则西半球时区的构建机会把日期显示成前一天。
页面由数据反推
分类页、标签页、归档页、站点地图、RSS和搜索索引,全部由同一份文章列表在构建时生成,不需要手工维护任何清单。新增一篇文章后,这些页面自动同步。
const posts = await getCollection('posts', ({ data }) => !data.draft);
const sorted = posts.sort((a, b) =>
b.data.pubDate.valueOf() - a.data.pubDate.valueOf()
);
getCollection()返回顺序是不确定的,任何依赖顺序的地方都必须自己排序,这一点文档里也写了,但很容易漏。
上线前检查清单
- 配置站点绝对地址,它会决定canonical、OG标签、sitemap和RSS里的链接;
- 所有静态页面统一以斜杠结尾,Nginx里配好
try_files或$uri/index.html; - 检查404页是否真的返回404状态码,而不是软404;
- 把
robots.txt里的sitemap地址改成正式域名; - 用构建产物本地起一次服务验证,别只信开发服务器。
静态站点真正的优势不是快,而是几乎没有什么会坏。这一点在两年后回来改一篇旧文章时,会显得格外值钱。
评论 0
评论保存在本站服务器,无需登录。带「作者」标识的是站主回复,请友善交流。
还没有评论,来写第一条。