2172 字
11 分钟
Astro 入门:以内容为中心的现代 Web 框架

1. 引言#

Astro 是一个专为内容驱动型网站设计的 Web 框架。它的核心理念很简单:大部分页面内容不需要 JavaScript,就不应该发送 JavaScript。

在 React/Vue 社区卷服务端渲染、卷流式传输、卷一切的时候,Astro 走了一条完全不同的路:

你的博客文章、文档页面、营销网站,99% 的内容是静态的。为什么要为这 99% 的部分加载一个完整的 JS 运行时?

这个思路让 Astro 一炮而红——它连续两年(2023/2024)获得「前端满意度」第一名,并在 2025 年成为 GitHub 上 Star 增长最快的 Web 框架之一。

(你正在看的这个博客就是用 Astro 构建的。)


2. 岛屿架构:Astro 的杀手锏#

2.1 传统 SPA 的问题#

传统的 React/Vue 单页应用:

整个页面 = 一个巨大的 JS 应用
├── 导航栏(需要交互)
├── 文章内容(纯静态文字)
├── 侧边栏(纯静态)
├── 评论区(需要交互)
└── 页脚(纯静态)

加载这个页面,浏览器要下载整个应用的 JS,然后「水合」全部组件。即使 80% 的内容永远不会变化,也要为它们付出 JS 的代价。

2.2 Astro 的答案#

整个页面 = 纯 HTML(默认)
├── 导航栏 → 纯 HTML(零 JS)
├── 文章内容 → 纯 HTML(零 JS)
├── 侧边栏 → 纯 HTML(零 JS)
├── 🏝️ 评论区 → React 组件(按需水合)
└── 🏝️ 点赞按钮 → Vue 组件(按需水合)

这就是岛屿架构:页面默认是静态 HTML,只有真正需要交互的部分才作为「岛屿」加载 JS。每个岛屿独立加载、独立水合,互不干扰。


3. 创建第一个 Astro 项目#

3.1 初始化#

Terminal window
# npm
npm create astro@latest my-site
# pnpm(推荐)
pnpm create astro@latest my-site

初始化向导:

✔ How would you like to start? → Empty
✔ Do you plan to write TypeScript? → Yes
✔ How strict should TypeScript be? → Strict
✔ Install dependencies? → Yes
✔ Initialize a new git repository? → Yes

启动开发服务器:

Terminal window
cd my-site
pnpm dev

访问 http://localhost:4321,你的第一个 Astro 站点就跑起来了。

3.2 项目结构#

my-site/
├── astro.config.mjs # Astro 配置文件
├── src/
│ ├── pages/ # 路由页面(文件系统路由)
│ │ ├── index.astro # 首页 /
│ │ ├── about.astro # /about
│ │ └── blog/
│ │ └── [slug].astro # 动态路由 /blog/xxx
│ ├── components/ # 可复用组件
│ ├── content/ # 内容集合(博客文章等)
│ ├── layouts/ # 页面布局
│ └── styles/ # 全局样式
├── public/ # 静态资源(直接复制到构建产物)
└── package.json

4. Astro 组件语法#

4.1 基础结构#

.astro 文件由两部分组成:组件脚本(服务端运行)和模板(输出 HTML)。

---
// 组件脚本(fence):在服务端/构建时运行
// 可以 import 其他组件、调用 API、查数据库
const name = "Astro";
const items = ["SSG", "岛屿架构", "多框架"];
---
<!-- 模板部分:直接输出 HTML -->
<h1>你好,{name}!</h1> <!-- { } 内嵌 JS 表达式 -->
<ul>
{items.map(item => <li>{item}</li>)}
</ul>

关键区别--- 之间的代码运行在服务端(构建时),不会发送到浏览器。模板部分输出纯 HTML。

4.2 Props 和插槽#

components/Card.astro
---
export interface Props {
title: string;
subtitle?: string;
}
const { title, subtitle } = Astro.props;
---
<div class="card">
<h2>{title}</h2>
{subtitle && <p class="subtitle">{subtitle}</p>}
<!-- 插槽:父组件可以插入内容 -->
<slot />
</div>
<style>
/* 组件级样式,默认 scoped */
.card {
padding: 1.5rem;
border-radius: 12px;
background: #fff;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
.subtitle {
color: #666;
font-size: 0.9rem;
}
</style>

使用这个组件:

---
import Card from '../components/Card.astro';
---
<Card title="Astro 入门" subtitle="从零开始">
<p>这是一段插入到 slot 中的内容。</p>
</Card>

4.3 样式默认隔离#

Astro 的 <style> 标签默认 scoped——样式只作用于当前组件,不会泄露到页面的其他部分。这是内置能力,不需要 CSS Modules 或 styled-components。

<!-- 这个 h1 样式只影响本组件 -->
<style>
h1 { color: red; }
</style>
<!-- 如果需要全局样式 -->
<style is:global>
:root {
--primary: #3b82f6;
}
</style>

5. 内容集合(Content Collections)#

对于博客、文档站这类以内容为主的站点,Astro 提供了内容集合——一个类型安全的内容管理系统。

5.1 定义集合#

src/content/config.ts
import { defineCollection, z } from 'astro:content';
const blogCollection = defineCollection({
type: 'content', // 'content' 表示 Markdown/MDX
schema: z.object({
title: z.string(),
published: z.date(),
description: z.string().optional(),
tags: z.array(z.string()).default([]),
draft: z.boolean().default(false),
}),
});
export const collections = {
blog: blogCollection,
};

5.2 编写内容#

src/content/blog/hello-world.md
---
title: 你好世界
published: 2026-06-17
tags: [Astro, 博客]
---
这是我的第一篇 Astro 博客文章。

5.3 查询和渲染#

src/pages/blog/index.astro
---
import { getCollection } from 'astro:content';
const posts = await getCollection('blog', ({ data }) => {
return import.meta.env.PROD ? !data.draft : true;
});
// 按日期排序
posts.sort((a, b) => b.data.published.valueOf() - a.data.published.valueOf());
---
<h1>博客</h1>
<ul>
{posts.map(post => (
<li>
<a href={`/blog/${post.slug}`}>{post.data.title}</a>
<time>{post.data.published.toLocaleDateString()}</time>
</li>
))}
</ul>

6. 混合使用其他框架#

Astro 最神奇的地方:你可以在同一个页面用 React、Vue、Svelte 组件。

6.1 添加集成#

Terminal window
# 添加 React 支持
pnpm astro add react
# 添加 Vue 支持
pnpm astro add vue
# 添加 Svelte 支持
pnpm astro add svelte

6.2 在 Astro 中使用框架组件#

pages/island-demo.astro
---
import ReactCounter from '../components/ReactCounter.jsx';
import VueTodoList from '../components/VueTodoList.vue';
import SvelteChart from '../components/SvelteChart.svelte';
---
<!-- 静态内容,Astro 直接渲染为 HTML -->
<h1>多框架演示</h1>
<p>下面的组件来自不同的框架:</p>
<!-- React 组件 -->
<ReactCounter client:load />
<!-- Vue 组件 -->
<VueTodoList client:visible />
<!-- Svelte 组件 -->
<SvelteChart client:idle />

6.3 client 指令:控制水合时机#

每个框架组件都需要一个 client:* 指令来决定何时加载 JS:

指令行为适用场景
client:load页面加载后立即水合高优先级交互(如导航菜单)
client:idle浏览器空闲时水合低优先级交互
client:visible组件进入视口时水合页面下方的交互组件
client:media匹配媒体查询时水合仅在移动端加载的组件
client:only跳过 SSR,仅客户端渲染依赖浏览器 API 的组件
<!-- 示例:在不同时机加载不同组件 -->
<MobileMenu client:media="(max-width: 768px)" />
<SearchDialog client:idle />
<CommentSection client:visible />
<ThemeToggle client:load />

7. 路由与页面模式#

7.1 SSR 模式(默认)#

Astro 默认是 SSG(构建时生成纯 HTML)。如果需要 SSR(每次请求动态渲染),在文件顶部加上:

---
export const prerender = false;
---
<!-- 这个页面在每次请求时动态渲染 -->
<h1>当前时间:{new Date().toLocaleTimeString()}</h1>

或者在 astro.config.mjs 中全局启用:

export default defineConfig({
output: 'server', // 或 'hybrid'(混合模式)
});

7.2 三种输出模式#

模式说明适用场景
static(默认)构建时生成全静态 HTML博客、文档站、官网
server每次请求在服务端渲染需要动态数据的站点
hybrid大部分页面静态,少数页面动态静态博客 + 登录/搜索功能

8. Astro vs 其他框架#

维度AstroNext.jsNuxt
核心理念零 JS 默认,岛屿增强React 全栈框架Vue 全栈框架
默认渲染SSGSSGSSG
JS 体积极低(默认 0KB)中等中等
多框架支持✅ 原生支持❌ 仅 React❌ 仅 Vue
学习曲线平缓(类 HTML 模板)陡峭(RSC、App Router)中等
最佳场景博客、文档、营销站复杂全栈应用复杂全栈应用
构建速度极快(Go + Rust 引擎)中等中等

9. 什么时候选 Astro?#

选择 Astro 的典型信号:

场景理由
个人博客纯静态,零 JS,Lighthouse 满分
技术文档站内容为主,极少交互
公司官网 / 营销页首屏要快,SEO 要求高
电商展示页商品展示为主,交互通过岛屿
微前端聚合不同团队用不同框架,Astro 统合输出

不选 Astro 的信号:

场景推荐替代
极度复杂的前端交互(如在线 Excel)React / Vue SPA
需要客户端状态管理贯穿全站Next.js / Nuxt
团队已经深度投入某个框架生态在其生态内选方案

10. 小结#

Astro 的成功来自一个简单的观察:大多数网站的「交互」可能就几个按钮,但传统框架为整站加载了一个重型运行时。

它的设计哲学可以总结为:

默认输出 HTML,按需注入 JavaScript。「多框架」不是噱头,而是解决了一个现实问题——不同团队、不同场景可以各用擅长的工具,最终由 Astro 统合为最佳性能的静态站点。

如果你要建一个博客、文档站、营销页面,或者任何「内容 > 交互」的网站,Astro 可能是目前的最佳选择。就像这个博客一样——你现在看到的每一篇文章,都是 Astro 在构建时生成的纯 HTML,没有任何多余的 JS。

学习路径建议:
1. 用 Astro 搭一个个人博客(3~5 天)→ 理解 SSG 和内容集合
2. 加入一两个 React/Vue 岛屿组件(1~2 天)→ 理解岛屿架构
3. 尝试 hybrid 模式,添加搜索功能(3~5 天)→ 理解动态路由
Astro 入门:以内容为中心的现代 Web 框架
https://www.hehonglei.cn/technology/astro-intro/
作者
Honglei He
发布于
2026-06-17
许可协议
CC BY-NC-SA 4.0