Astro 入门教程:群岛架构与内容驱动
一、Astro 是什么?
Astro 是专注于内容驱动网站的现代静态站点生成器。它的核心理念是"Islands Architecture(群岛架构)"——页面默认是纯静态 HTML(零 JavaScript),仅在需要交互的地方引入"岛屿"(React/Vue/Svelte 组件水合到页面中)。
为什么这很重要?
传统 SPA 框架下,一个博客首页可能加载 200KB+ 的 JavaScript,而 Astro 的同一页面可能仅 0KB。对于文档站、营销站、电商产品页等以内容为主的场景,这是巨大的性能优势。
二、Islands Architecture 详解
┌─────────────────────────────────────┐
│ 纯 HTML 海洋 │
│ (导航栏、标题、正文、页脚) │
│ │
│ ┌─────────┐ ┌──────────────┐ │
│ │ React │ │ Svelte │ │
│ │ 轮播图 │ │ 实时搜索 │ │
│ └─────────┘ └──────────────┘ │
│ ↑ 水合岛屿 ↑ 另一个岛屿 │
└─────────────────────────────────────┘
client 指令控制水合时机
| 指令 |
水合时机 |
适用场景 |
client:load |
页面加载后立即 |
关键交互(导航菜单) |
client:idle |
浏览器空闲时 |
低优先级组件 |
client:visible |
进入视口时 |
懒加载组件(评论区) |
client:media |
匹配媒体查询时 |
响应式组件 |
client:only |
仅客户端渲染 |
依赖浏览器 API 的组件 |
三、内容集合(Content Collections)
Astro 2.0+ 的核心特性,为 Markdown/MDX 提供类型安全:
import { defineCollection, z } from "astro:content";
const blogCollection = defineCollection({
type: "content",
schema: z.object({
title: z.string(),
date: z.date(),
description: z.string().optional(),
tags: z.array(z.string()).default([]),
draft: z.boolean().default(false),
}),
});
export const collections = { blog: blogCollection };
使用:
---
import { getCollection } from "astro:content";
const posts = await getCollection("blog", ({ data }) => !data.draft);
const sortedPosts = posts.sort(
(a, b) => b.data.date.getTime() - a.data.date.getTime()
);
---
<ul>
{sortedPosts.map((post) => (
<li>
<a href={`/blog/${post.slug}`}>{post.data.title}</a>
<time>{post.data.date.toLocaleDateString()}</time>
</li>
))}
</ul>
四、路由系统
src/pages/
├── index.astro → /
├── about.astro → /about
├── blog/
│ ├── index.astro → /blog
│ └── [slug].astro → /blog/:slug(动态路由)
├── rss.xml.js → /rss.xml(API 端点)
└── 404.astro → 自定义 404
动态路由 + SSG
---
export async function getStaticPaths() {
const posts = await getCollection("blog");
return posts.map((post) => ({
params: { slug: post.slug },
props: { post },
}));
}
const { post } = Astro.props;
const { Content } = await post.render();
---
<article>
<h1>{post.data.title}</h1>
<Content />
</article>
五、视图过渡(View Transitions)
Astro 3.0+ 内置 SPA 般的页面过渡:
---
import { ViewTransitions } from "astro:transitions";
---
<html>
<head>
<ViewTransitions />
<!-- 页面切换时自动应用原生 View Transition API -->
</head>
<body>
<slot />
</body>
</html>
六、部署
npm run build
七、思考题
- "零 JS" 真的意味着完全不能用 JavaScript 吗?什么情况需要 JS?
- Islands Architecture 和 Micro Frontends 有何异同?
- 如果一个页面有 20 个交互组件,Islands Architecture 还会有性能优势吗?
Astro 内容站点搭建入门
背景
Astro 是专为内容型网站设计的框架。如果你的毕设涉及博客、文档站、作品展示、公司官网等内容为主的项目,Astro 的"默认零 JS"理念能让你获得近乎完美的 Lighthouse 分数。同时它支持混合 Vue/React/Svelte 组件——这在答辩中是非常独特的卖点。
核心概念
岛屿架构
Astro 把页面想象成海洋,交互组件是岛屿:
┌────────────────────────────┐
│ 纯 HTML (海洋) │
│ │
│ ┌──────┐ ┌──────────┐ │
│ │ Vue │ │ React │ │
│ │ 岛屿 │ │ 岛屿 │ │
│ └──────┘ └──────────┘ │
│ │
│ 不需要 JS 的内容完全不加载 JS │
└────────────────────────────┘
.astro 单文件组件
---
const data = await fetch('https://api.example.com/posts');
const posts = await data.json();
---
<!-- HTML 模板 -->
<h1>博客文章</h1>
{posts.map(post => <PostCard {...post} />)}
分步操作
第一步:创建项目
npm create astro@latest
cd my-site
npm run dev
第二步:理解路由
src/pages/
├── index.astro → /
├── about.astro → /about
├── blog/
│ ├── index.astro → /blog
│ └── [slug].astro → /blog/post-1
└── 404.astro → 404 页面
第三步:添加框架
npx astro add react
然后就可以在 .astro 文件中使用 React 组件:
---
import Counter from '../components/Counter.jsx';
---
<Counter client:load /> <!-- client:load 表示在客户端水合 -->
第四步:Content Collections
import { defineCollection, z } from 'astro:content';
const blogCollection = defineCollection({
schema: z.object({
title: z.string(),
date: z.date(),
description: z.string(),
}),
});
export const collections = { blog: blogCollection };
毕设推荐场景
作品展示站
展示毕设项目截图、技术栈、GitHub 链接。纯静态,加载快。
技术博客
记录毕设开发过程,Markdown 写作,自动生成 RSS。
多框架实验
一个页面同时用 Vue 表单 + React 图表 + Svelte 动画——展示技术广度。
思考题
- Astro 的岛屿架构与传统 SPA 的水合(Hydration)有什么区别?
client:load vs client:visible 分别适用于什么场景?
- Content Collections 相比直接 import Markdown 有什么优势?
小结
Astro 是内容网站的终极方案。毕设中的作品展示、技术博客、文档页用它搭建,可以获得满分 Lighthouse 评分 + 独特的岛屿架构谈资。