博客从 Hexo/Hugo 那些旧东西迁到 Astro 后,我越来越觉得“最佳实践”这个词有点大。对个人博客来说,很多实践其实就是别给未来的自己挖坑。
我给这个站留几条规矩,后面继续写 Astro 相关内容时也按这个来。
URL 先稳住
老文章的 URL 不要随便变。
这个站以前的文章路径是 年/月/日/id/,现在迁到 Astro 之后也继续保留。新文章我也按日期放,路径末尾统一带 /。这样做不酷,但稳。
我宁愿路径不好看,也不想让搜索引擎、RSS 阅读器、别人收藏的链接全部失效。迁移站第一优先级不是换新门面,是让旧门牌还能找到原来的屋子。
frontmatter 宁愿重复,也别靠猜
现在每篇文章都有 path、permalink、slug、tags、tagSlugs、categories、categorySlugs。看起来有点啰嗦,但我愿意接受。
以前很多静态博客工具喜欢“根据文件名帮你生成”。这当然方便,可是旧文章一多,文件名、标题、slug、中文标签混在一起,出问题时很难查。
我现在更喜欢把关键 SEO 字段写清楚。页面地址从 path 来,canonical 可以从 permalink 来,分类和标签的 slug 单独维护。笨一点,但少猜一点。
Content Collections 要写 schema
Astro 的 Content Collections 最适合管这种文章堆。src/content.config.ts 里把字段定下来以后,构建阶段就能发现脏数据。
我会继续保持这几个字段必填:
title: z.string(),
date: z.coerce.date(),
excerpt: z.string(),
path: z.string(),
tags: z.array(z.string()).default([]),
categories: z.array(z.string()).default([]),
尤其是 date,我会用 z.coerce.date()。旧文章里日期格式不一定统一,让它在集合层统一处理,比在列表页里临时转来转去好。
Markdown 能静态就静态
Astro 现在有 build-time collections,也有 live content collections。这个博客我会继续用 build-time。
原因很简单:文章不是股票价格,不需要每次请求都查外部数据。静态生成之后,页面能被 CDN 安安稳稳缓存。对个人博客来说,这就是最省心的方案。
以后如果加“最近听的歌”“随机说说”“在线状态”这种东西,再考虑 endpoint 或 live collection。正文文章先别动。
图片尽量回到自己手里
旧文章里的图床链接,我已经尽量搬回本地。剩下一些 404 或 SSL 出错的图,只能先留着。
这件事给我的提醒是:图片不要全压在别人服务上。文章文字还在,图没了,很多教程就废一半。截图类文章尤其明显。
后面新文章我会尽量把图片放进项目里,或者至少保证有可替换的本地路径。仓库会变大一点,但十年后能打开,比现在看着轻巧更重要。
SEO 不要玄学化
这个站该做的 SEO 其实就几件事:
- 每页一个稳定 canonical。
- 首页、分页、文章页有清楚的 title 和 description。
- sitemap 和 RSS 正常生成。
- 404 不要被索引。
- OG 图有默认值,文章有图时再覆盖。
剩下的就是内容本身。以前写 Hexo 教程时,很多访问来自搜索。那些文章能活下来,不是因为塞了多少关键词,而是确实有人遇到同样的问题。
所以新 Astro 文章也一样,写自己真踩过的坑,别写成产品介绍。
少上岛
Astro 的 island 很好用,但博客页面没必要到处 hydration。
文章列表、归档、标签、正文,这些都是静态 HTML 就能解决的东西。真的需要交互,再加 client:load、client:visible 之类的指令。不要因为框架支持 React/Vue/Svelte,就每个小按钮都塞一个组件进去。
静态博客最舒服的地方,就是没多少 JS 也能读。这个优点别丢。
每次改完都跑构建
我现在改博客会固定跑:
npm run astro -- sync
npm run build
如果改了分页,还会打开首页、中间页、最后一页看一眼。比如第 12 页这种位置,最容易暴露分页窗口逻辑有没有写歪。
恢复旧站这种事,不怕慢,怕自信。多跑一次构建,多点几个老链接,能省掉很多上线后的尴尬。
最后
Astro 6 和 7 加了不少东西,但这个旧博客不会急着把每个新功能都用上。我的顺序还是:旧链接、正文、图片、RSS、sitemap、分页、SEO。基础稳了,再慢慢换更好的字体、安全策略和缓存。
框架会继续升级,博客最好别跟着一起乱跳。
参考: