用 Astro 与 Cloudflare 搭建这个博客
约 2 分钟
这个站点的目标很朴素:写文章要顺手,读文章要快。围绕这两点,选型基本是被推导出来的。
静态优先
博客的内容在构建时就已确定,没有任何需要按请求计算的东西。所以输出纯静态 HTML,由 Cloudflare 的边缘节点直接返回,首字节时间只取决于最近的节点距离。
需要注意的是,静态并不等于没有交互。主题切换这类局部交互用一小段内联脚本就够了,不需要为此引入前端框架:
const root = document.documentElement;root.dataset.theme = root.dataset.theme === 'dark' ? 'light' : 'dark';Astro 默认不向浏览器发送组件运行时,页面里出现的 JS 是你自己写的那几行。
内容用 Content Layer 管
文章放在 src/content/posts/,通过 src/content.config.ts 里的 schema 校验 frontmatter:
const posts = defineCollection({ loader: glob({ base: './src/content/posts', pattern: '**/*.{md,mdx}' }), schema: z.object({ title: z.string().max(120), pubDate: z.coerce.date(), draft: z.boolean().default(false), }),});好处是写错字段名会在构建时报错,而不是等页面渲染出空白才发现。draft: true 的文章只在本地开发时可见。
Tailwind 4 的配置方式
Tailwind 4 把配置搬回了 CSS。设计 token 直接写在 @theme 里,深色模式则是覆盖同名变量,不需要给每个元素挂 dark: 变体:
@theme { --color-ink: oklch(0.22 0.01 260);}
:root[data-theme='dark'] { --color-ink: oklch(0.93 0.008 260);}颜色用 oklch 而不是 hex,是因为它的亮度分量感知均匀,调深浅时不会顺带改变饱和度观感。
取舍
有几个决定值得说明:
- 不上 SSR。 评论、搜索这类动态功能,可以等真的需要时再接第三方服务或加一个 Worker,没必要现在就把整站放进运行时。
- 依赖锁精确版本。
package.json里不带^,升级是显式动作,避免某次安装静默引入 breaking change。 - CI 跑完整校验。 格式、lint、类型、构建四步,任一失败就不部署。
下一步
把 src/consts.ts 里的站点信息换成你自己的,删掉这篇示例,就可以开始写了。