Astro — 内容站点优先的 Web 框架
是什么
Astro 是一个内容站点优先的 Web 框架——专门用来写”博客 / 文档 / 营销页 / 教程站”这种内容多、交互少的站点。它默认输出 0 KB JavaScript 的纯 HTML,浏览器只下载真正需要的那一点点 JS。
日常类比:next-js 是带服务的全餐厅——服务员(JS)从你坐下开始就在桌边转;Astro 是只摆好菜的自助快餐——不需要服务员就能吃,只有要点鸡尾酒(交互组件)的时候才叫人来。
你写一个 index.astro:
---const greeting = "hi"---<h1>{greeting}</h1>构建出来就是一个 <h1>hi</h1> 的 HTML 文件,前端 0 KB JS。读者打开页面看到内容那一刻,没有任何脚本在后台 hydration。
我们这个 study 站本身就是 Astro + starlight 写的。
为什么重要
不理解 Astro,下面这些事都没法解释:
- 为什么 2022 年起一堆文档站(Bun docs / Cloudflare docs / Vercel 博客)都从 next-js 迁到了 Astro
- 为什么”Islands Architecture”(孤岛架构)从 2021 年成了前端通用术语——这词是 Astro 团队推广开的
- 为什么 Astro 项目里能同时出现
<ReactCounter />和<VueChart />而不打架 - 为什么写 Markdown 在 Astro 里像在 Notion 里一样自然——MDX 是一等公民
Astro 的核心价值有四点:
- 默认 0 JS:内容站点不该让用户下载 React runtime + 业务代码再”水合”——直接给 HTML
- Islands Architecture:页面是一片静态海,需要交互的小块(搜索框 / 计数器)才是”岛”,按需激活
- 多框架混用:同一个项目里可以用 React 写复杂表单、用 Vue 写图表、用 Svelte 写动画——彼此独立打包
- Markdown / MDX 一等公民:写文档不用配
gatsby-transformer-remark那一堆插件,开箱即用
核心要点
Astro 之所以能”内容快 + 灵活”,靠 三个设计:
-
Islands Architecture(孤岛架构)
- 默认所有组件只在构建时渲染成 HTML(SSG),不带 JS 到客户端
- 想要交互?给组件加
client:*指令——这块组件就成为一座”岛”,单独打包它的 JS - 指令选项:
client:load(立即水合)/client:idle(浏览器空闲时)/client:visible(滚动到可见时)/client:media(满足媒体查询时) - 类比:一片海上零星几座岛——海水(HTML)不要 JS,岛(交互组件)才用 JS
-
多框架支持
-
Content Collections(内容集合)
src/content/<集合名>/*.md是一个”集合”,配上 zod schema 定义 frontmatter 字段- 类比:Notion 里的 database——每条记录字段统一、有类型校验
- 写错字段(如
pubDate写成字符串而非 Date)构建直接报错,不会到运行时才挂
实践案例
案例 1:.astro 文件长什么样
src/pages/index.astro:
---const greeting = "hi"const items = ["苹果", "香蕉", "橙子"]---<h1>{greeting}</h1><ul> {items.map((it) => <li>{it}</li>)}</ul>逐部分解释:
---之间是 frontmatter(不是 markdown 那种 yaml,而是真正的 JavaScript)——构建时执行---之后是模板,语法像 JSX 但更接近 HTML:直接<h1>而不是<h1></h1>也行{greeting}/{items.map(...)}是表达式插值——和 JSX 一样- 构建产物是一个纯 HTML 文件,没有任何 JS。浏览器看到的是
<h1>hi</h1><ul><li>苹果</li>...
案例 2:什么时候用 client:visible 而不是 client:load
---import Counter from "../components/Counter.jsx"import Footer from "../components/Footer.jsx"---<Counter client:load /><Footer client:visible />为什么这么分:
Counter在首屏顶部、用户进来就能看见——client:load立即水合(不等不行)Footer在页面底部、用户可能根本不滚下去——client:visible等滚到再水合,省掉这部分 JS 的下载 + 解析- 在长文档站点里,正确用
client:visible能让首屏 JS 体积减少 50%+,Lighthouse 分数立刻好看
类比:餐厅里靠门的桌子立刻摆餐具(client:load),里间的桌子等有客人进去再摆(client:visible)——省人力。
案例 3:Content Collections 的 schema 校验
src/content/config.ts:
import { defineCollection, z } from "astro:content"
const blog = defineCollection({ type: "content", schema: z.object({ title: z.string(), pubDate: z.date(), draft: z.boolean().default(false), }),})
export const collections = { blog }逐部分解释:
defineCollection注册一个内容集合,schema定义 frontmatter 必须长什么样- zod 是 schema 验证库——
z.string()/z.date()表示这个字段必须是字符串 / 日期 - 写一篇
src/content/blog/hello.md时如果 frontmatter 缺title或pubDate不是日期,构建直接报错——不会到生产环境才发现 - 配合 TypeScript,模板里
post.data.title是有类型的——拼错字段名 IDE 会高亮
踩过的坑
-
复杂状态用 Astro 自身组件吃力:
.astro组件不能在客户端管状态——它就是 SSG 模板。需要useState/ 双向绑定的地方必须用 React / Vue / Svelte 客户端组件。新手常想”我能不能在 .astro 里写 onClick”——不能。 -
Markdown 里写 JSX 必须用 .mdx 不能 .md:默认
.md文件是纯 Markdown,写<MyComponent />不会渲染成组件——它会被当成 HTML 字符串原样输出。要嵌组件必须文件名改成.mdx,并装@astrojs/mdxintegration。 -
Astro 5 升级 Content Layer 与老 collections 不兼容:Astro 5(2024 末发布)把 Content Collections 重写成 Content Layer——支持从远程 API / CMS 拉数据。老项目升级要改
defineCollection的写法,没看 migration guide 直接升大概率构建报错。 -
View Transitions 只在浏览器层面,不是真 SPA:Astro 提供
<ClientRouter />用 [浏览器原生 View Transitions API] 做页面切换的过渡动画——但它不是 React Router 那种 SPA:每次切换仍然是新页面,只是浏览器在切换瞬间渲染一次过渡。不支持 View Transitions API 的浏览器(老版 Safari)会直接整页刷。
适用 vs 不适用场景
适用:
- 文档站 / 博客 / 营销页 / 教程站——内容多 + 交互少 + 要 Lighthouse 满分
- 需要多框架混用的迁移场景——老项目慢慢从 Vue 迁到 React,用 Astro 当壳
- 写 Markdown / MDX 为主的内容平台——Content Collections 比 next-js 的
getStaticProps顺手太多 - 个人博客 / 实习日志——这个 study 站就是
不适用:
- 高度交互的 web app(dashboard / SaaS / 编辑器)——核心价值是状态管理和路由,next-js / react SPA 更顺
- SSR 为主、需要每个请求动态渲染——Astro 能 SSR 但不是它的强项
- 强依赖某个框架的生态(如要用 Next.js 的 ISR + 边缘函数 + middleware)——直接上 next-js
- 团队完全没有前端经验——Astro 的学习曲线在”什么时候加 client:* 指令”这类决策上有门槛
历史小故事(可跳过)
- 2021 年 6 月:Fred K. Schott(Snowpack 作者)在博客发文宣布 Astro 0.1,提出 “Islands Architecture” 一词
- 2022 年 8 月:Astro 1.0 发布,定位明确为”内容优先 + 多框架混用”
- 2023 年:Starlight(Astro 出品的文档主题)发布——Bun / Cloudflare / Vercel 部分文档迁过来
- 2024 年末:Astro 5 发布,Content Layer 重写,支持 server islands(服务端按需渲染的岛)
- 2026 年:成为 Markdown / MDX 静态站点事实标准之一,与 next-js / vitepress 并列
学到什么
- 默认值的力量:next-js 默认带 React runtime;Astro 默认 0 JS。默认值就是文化——决定团队 90% 的代码长什么样
- 架构选择 = 假设选择:Islands 架构假设”页面大部分是静态内容”——这假设对内容站成立、对 SaaS dashboard 不成立
- 指令式优化(client:visible)比配置式优化(webpack chunkSplit)更直观:让作者在写组件那一刻决定”这块要不要 lazy”——不用打包工具替你猜
- 多框架共存是兼容代价:能混用是好事;同一项目用三个框架是噩梦——能力 ≠ 应该
延伸阅读
- 官方 docs:docs.astro.build——产品功能 + Islands Architecture 的官方解释
- 源码:github.com/withastro/astro——TypeScript 实现的 compiler + runtime
- starlight —— Astro 出品的文档主题,本 study 站在用
- next-js —— Astro 的常被对比对象;选哪个看”内容站还是 web app”
关联
- starlight —— Astro 出品的文档主题;本站点用的就是它
- next-js —— Astro 的近邻 + 常被对比;前者 web app 优先,后者内容优先
- react —— Astro 里最常用的客户端组件框架,通过
@astrojs/react集成 - vue —— 通过
@astrojs/vue集成;可以与 React 在同一站点共存 - svelte —— 通过
@astrojs/svelte集成;编译成原生 DOM 操作,岛体积更小 - solid —— 通过
@astrojs/solid-js集成;细粒度响应式,适合性能敏感岛 - preact —— React 兼容但更小的轻量替代;Astro 推荐用它降低 runtime 体积
- vite —— Astro 5 起底层构建工具切到 Vite;dev server / HMR 全靠它
- markdown-it —— Astro 默认 markdown 解析器底层就是它
- zod —— Content Collections schema 验证用的就是 zod
反向链接
- changesets —— changesets — 让每个 PR 自带版本号 bump 声明
- docusaurus —— Docusaurus — 一组 plugin 协作出来的文档站框架
- i18next —— i18next — 让一份 JS 代码同时讲几十种语言
- lighthouse —— Lighthouse — Google 出品的网页质量审计工具
- lucia —— Lucia — 主动把自己降级为”学习资源”的 TS 认证库
- markdown-it —— markdown-it — 把 Markdown 文本变成 HTML 的工业级解析器
- micromark —— micromark — markdown 解析器里那台一个字一个字读的状态机
- minisearch —— minisearch — 浏览器里的小型全文搜索引擎
- motion-one —— Motion One — 把动画交给浏览器自己跑
- next-js —— Next.js — React 全栈框架
- nextra —— Nextra — 在 Next.js 上盖一层文档站脚手架
- nuxt —— Nuxt — Vue 全栈框架
- observable-framework —— Observable Framework — 编译期跑数据,浏览器只看结果
- oxc —— oxc — Rust 写一整套 JS/TS 工具链的勇气
- preact —— Preact — 3KB React 替代
- react —— React UI 组件库
- remix —— Remix — 拥抱 Web 标准的 React 全栈框架
- shadcn-ui —— shadcn/ui — 把 React 组件从 npm 包变成”源码 + CLI 协议”
- solid —— SolidJS — 细粒度响应式 UI 框架
- starlight —— Starlight — Astro 文档站点主题
- svelte —— Svelte — 编译时 UI 框架
- unified —— unified — 把文档处理拆成 AST + plugin 流水线
- valibot —— Valibot — 拆成乐高的 TypeScript 校验库
- vanilla-extract —— vanilla-extract — 把 CSS 写成 TypeScript,浏览器看到的却是零字节运行时
- vite —— Vite — 浏览器自己加载源码的构建工具
- vitepress —— VitePress — Vue 团队用 Vite 写的静态文档站点生成器
- vue —— Vue.js — 渐进式 UI 框架
- web-vitals —— web-vitals — 让你在自己页面测的数和 Google 排名用的数对得上
- zod —— Zod — TypeScript-first schema 验证