在构建内容型网站时,我们总在性能、开发体验与组件化之间反复横跳。传统静态站点生成器虽然加载快,但缺乏组件生态; 现代前端框架虽强大,却往往带来冗余的 JS 和复杂的构建逻辑。
在现代前端框架百花齐放的今天,Astro 凭借其独特的构建模型和“零 JavaScript 默认加载”理念,正在成为静态站点领域的明星选手。 从调查数据可以看到越来越多的开发者将网站迁移或者正在使用 Astro 。
Astro 作为一个以 HTML 优先、 JS 最小化的现代框架,重新定义了“静态站点生成器”。 它不仅支持 React、Vue、Svelte 等多框架组件混用,还以群岛架构(Island Architecture)为核心,做到 只为需要交互的部分加载 JS , 在保持现代开发体验的同时,实现前所未有的页面性能表现。
Astro 构建时默认输出纯 HTML,除非显式标记需要交互的组件,否则页面不会附带任何 JS,这在性能上领先大多数现代框架。
传统前端架构主要有两种主流形式:多页应用(MPA) 和 单页应用(SPA)。二者各有优劣,但都在处理“交互组件 + 内容渲染 + 性能”三者之间存在取舍。 而群岛架构正是为了解决这个困局而提出的一种新范式。
“群岛” 架构的总体思想看似简单:在服务器上渲染 HTML 页面,并在高度动态的区域周围注入占位符或插槽 […] 这些区域随后可以在客户端 “激活” 成为小型独立的小部件,重用它们服务器渲染的初始 HTML。 — Jason Miller, Preact 的创造者 简单来说群岛的设计理念就是: 将网页划分为一片“静态内容的海洋”,其中嵌入少量具有交互性的“JavaScript 岛屿”。
在 Astro 中,“岛屿”指的是页面上的任何交互式 UI 组件。这种架构模式所依赖的技术也被称为 局部化或选择性激活。
这样做带来的好处有:
这种架构大幅减少 JS 体积,提升首屏加载速度,同时保留必要的组件交互能力。
架构类型 | 渲染方式 | JS 体积 | 首屏性能 | SEO 友好 | 状态管理 |
---|---|---|---|---|---|
SPA | 客户端渲染 | 重 | 较差 | 需额外优化 | 需要全局状态 |
MPA | 服务端渲染 | 少 | 较快 | 好 | 状态切换较复杂 |
Island | HTML + 局部交互 | 极小(按需) | 极快 | 极好 | 每个组件独立管理 |
Astro 实现岛屿架构的关键,是通过指令式 hydration(显式的客户端挂载标记)控制组件行为。
---
import Counter from '../components/Counter.jsx';
---
<Counter client:load />
<Counter client:idle />
<Counter client:visible />
<Counter client:only="react" />
client:*
指令,可以将任何 静态 UI 组件转变为交互式岛屿。然后 Astro 会自动构建并打包你的客户端 JavaScript,以优化性能。
指令 | 行为说明 |
---|---|
client:load | 页面加载后立即挂载组件 |
client:idle | 浏览器空闲时挂载(适合非核心组件) |
client:visible | 元素进入视口后挂载(适合懒加载场景) |
client:media | 匹配 media query 条件后挂载(响应式组件) |
client:only | 仅客户端渲染,跳过服务端 HTML 输出(如地图/播放器等) |
Astro 是一个以组件为单位编译输出 HTML 的框架,而不是像传统前端框架一样在客户端运行虚拟 DOM 或框架 runtime。 Astro 并不会将你写的 React/Vue/Svelte 组件直接交由浏览器运行,而是通过官方提供的集成包将这些组件在构建阶段“转换为 HTML”:
这些包的底层是基于 Vite 插件机制,通过 Vite 的 load/transform 钩子,动态编译各类组件,并将其包装为 Astro 可识别的组件模块。
# 安装某个框架支持包
npm install @astrojs/react
// astro.config.mjs
import react from "@astrojs/react";
export default {
integrations: [react()],
};
Astro 对组件的处理是**“边界隔离、语义清晰”**的:
.astro
文件是 Astro 原生模板语言,可直接引入 .jsx
, .vue
, .svelte
等任意组件;
每个非 .astro
组件都通过其对应框架的 SSR 渲染能力转为 HTML;
只在使用 client:\*
指令时才附带客户端框架 runtime,否则不会引入 React/Vue/Svelte 的 JS 代码。
因为框架 runtime 只对“岛屿”组件启用,组件之间互不影响,所以可以安心地在一个 Astro 页面中同时使用 React + Vue + Svelte 组件,这在其他主流框架中几乎是不可能实现的。
Astro 是为“内容优先的网站”设计的框架,特别适合博客、文档站、营销页等以内容为核心的场景。其对 Markdown / MDX 的原生支持使得内容开发变得更加高效、灵活。
.md 和 .mdx 文件即页面:可直接放在 src/pages/ 目录下自动生成路由;
Markdown 支持 Frontmatter:用于定义页面元数据(如标题、日期、分类等);
MDX 支持组件嵌入:可在 Markdown 中直接插入 React/Vue/Svelte 等组件,增强内容交互;
自动构建内容集合:通过 getCollection() API 可轻松管理内容数据;
Markdown 被编译为 HTML,无需手动处理 AST 或额外插件配置。
更多关于 Astro 中使用 Markdown 可以在 官网 查看
Astro 默认采用 Vite 作为底层构建器,Vite 本身已经支持:
JSX 编译(via esbuild)
Vue SFC(via @vitejs/plugin-vue)
Svelte(via @sveltejs/vite-plugin-svelte)
热更新、模块解析、多入口输出等
这意味着 Astro 只需加载合适的 Vite 插件,即可透明接入各种组件格式,并通过 SSR 转化为可渲染的 HTML 输出。这也是 Astro 可以同时支持不同框架的原因之一。
因为 Astro 输出的构建产物是纯 HTML/CSS/JS 文件,所以可直接部署到任意静态文件服务器或 CDN;官方也提供了适配器(@astrojs/netlify, @astrojs/vercel, @astrojs/static)简化部署配置。
更多关于 部署
Astro 倡导“最小必要结构”,避免过度抽象与复杂配置,让项目组织直观清晰、易于维护,非常适合多人协作与内容型项目开发。
Astro 默认目录结构:
src/
├── pages/ # 页面路由(自动对应 URL)
├── components/ # 可复用组件(支持多框架)
├── layouts/ # 页面布局组件
├── content/ # Markdown/MDX 内容集合(可选)
├── styles/ # 全局样式(可选)
├── scripts/ # 客户端 JS(可选)
public/ # 静态资源目录(如图片、字体)
astro.config.mjs # Astro 配置
每个目录的职责明确,零配置即可使用,避免结构分散和多层嵌套带来的维护困难。
Astro 采用的是文件系统驱动的路由机制,即页面的 URL 路径由 src/pages/ 目录结构自动生成。这种方式无需手动配置路由表,上手极其直观。
src/pages/
├── index.astro → /
├── about.astro → /about
├── blog/
│ ├── index.astro → /blog
│ └── [slug].astro → /blog/:slug(动态路由)
解释:
index.astro → /
about.astro → /about
blog/index.astro → /blog
blog/[slug].astro → /blog/hello-world(支持动态参数)
你只需要 创建对应的文件,就定义了一个页面路径 ,无需像 React Router 那样手动配置路径映射。
需要注意的是:动态路由必须导出一个 getStaticPaths()
,它返回一个具有 params
属性的对象数组。数组中的每一个对象都会生成相应的路由。
// src/pages/blog/[slug].astro
---
export async function getStaticPaths() {
return [
{ params: { slug: 'hello-world' } },
{ params: { slug: 'astro-guide' } },
];
}
const { slug } = Astro.params;
---
<h1>博客文章: {slug}</h1>
这样将生成两个页面 /blog/hello-world
、 /blog/astro-guide
;
文件名可以包含 多个参数 ,这些参数必须都包含在 getStaticPaths()
的 params
对象中:
// src/pages/blog/[slug]-[author].astro
---
export async function getStaticPaths() {
return [
{ params: { slug: 'helloworld', author: 'tom' } },
{ params: { slug: 'astroguide', author: 'jerry' } },
];
}
const { slug, author } = Astro.params;
---
<h1>博客文章: {slug}</h1>
<h1>作者: {author}</h1>
对应路由: /blog/helloworld-tom
、 /blog/astroguide-jerry
;
参数也可以包含在路径的单独部分中。例如, src/pages/blog/[slug]/[author].astro
文件与上面相同的 getStaticPaths()
将生成路由 /helloworld/tom
和 /astroguide/jerry
;
Astro 支持内置分页,用于需要分割成多个页面的大量数据。Astro 会生成常见的分页属性,包括上一页/下一页链接、总页数等。分页的路由名应该使用与标准动态路由一样的 [bracket]
语法,例如:
/astronauts/[page].astro
将生成 /astronauts/1
、/astronauts/2
等路由,其中 [page]
是生成的页码。
官方提供了 paginate()
内置函数帮助你快速生成这些页面
---
export async function getStaticPaths({ paginate }) {
const astronautPages = [{
astronaut: 'Neil Armstrong',
}, {
astronaut: 'Buzz Aldrin',
}, {
astronaut: 'Sally Ride',
}, {
astronaut: 'John Glenn',
}];
// 根据宇航员数组生成页面,每页2项
return paginate(astronautPages, { pageSize: 2 });
}
// 所有分页数据都在 "page" 参数中传递
const { page } = Astro.props;
---
<!-- 显示当前页面。也可以使用 Astro.params.page!-->
<h1>Page {page.currentPage}</h1>
<ul>
<!-- 列出宇航员信息数组 -->
{page.data.map(({ astronaut }) => <li>{astronaut}</li>)}
</ul>
因为 Astro 默认生成的是静态 HTML 页面,因此普通的 <a>
标签就可以完成页面跳转,无需前端框架 router。在纯 Astro 页中保持原生 <a>
标签比使用 <Link>
等 router 工具更高效。
Astro 是为内容导向的现代 Web 开发而生,极简、高效、易部署,是构建静态网站的理想选择。
如果你的项目目标是:快、静态、安全、SEO友好 —— Astro 是一个值得一试的选择。
你可以从这些方面考虑是否使用 Astro
类型 | 适配度 | 推荐理由 |
---|---|---|
内容型网站(博客、文档站) | ⭐⭐⭐⭐⭐ | Markdown 原生支持 + 静态输出,部署快,维护成本低 |
营销页 / Landing Page | ⭐⭐⭐⭐⭐ | 快速构建、零 JS 默认,加载速度极快 |
电商静态首页 / CMS 集成 | ⭐⭐⭐⭐ | 可与 Headless CMS 集成(如 Sanity/Contentful) |
传统 SSR 项目 | ⭐⭐⭐ | 适配 SSR/Edge 架构但不是强项,可按需使用 |
实时交互型 SPA / Dashboard | ⭐⭐ | 不太适合,推荐用纯 React/Vue 等实现 |