Astro 静态网站生成:内容网站开发笔记
静态站点生成器(SSG)常用于博客、文档和内容型网站。Astro 属于这一类框架,它的重点是尽量减少发送到浏览器端的 JavaScript。
什么是 Astro?
Astro 是一个 静态网站生成器,它的基本理念是:
尽可能少地向浏览器发送 JavaScript。
主要特性
- 零 JavaScript 默认策略
- 默认情况下,Astro 不向客户端发送任何 JavaScript
- 只在需要时才加载 JavaScript
- 群岛架构(Islands Architecture)
- 页面中的交互组件被隔离为「岛屿」
- 每个岛屿独立加载和水合
- 框架无关
- 支持 React、Vue、Svelte、Solid 等
- 可以在同一个项目中混用不同框架
性能优势
传统 SPA vs Astro
// 传统 SPA 加载过程
1. 下载 HTML (几 KB)
2. 下载 JavaScript bundle (几百 KB)
3. 解析和执行 JS
4. 渲染页面
5. 获取数据
6. 重新渲染
// Astro 加载过程
1. 下载 HTML + CSS (已包含完整内容)
2. 页面立即可见和可交互
3. (可选) 按需加载交互组件的 JS
性能指标对比
| 指标 | 传统 SPA | Astro |
|---|---|---|
| FCP | 2-3s | 0.5-1s |
| TTI | 3-5s | 0.5-1s |
| Bundle Size | 200-500KB | 0-50KB |
| Lighthouse | 60-80 | 95-100 |
示例:构建博客
1. 项目结构
src/
├── components/ # 可复用组件
├── layouts/ # 页面布局
├── pages/ # 路由页面
├── content/ # Markdown 内容
└── styles/ # 全局样式
2. 创建动态路由
// src/pages/blog/[slug].astro
---
import { getCollection } from 'astro:content';
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>
3. 组件岛屿
---
// 只在客户端加载和运行
import Counter from '../components/Counter.tsx';
---
<div>
<!-- 静态内容 -->
<h1>欢迎访问</h1>
<!-- 交互组件(岛屿) -->
<Counter client:load />
</div>
使用建议
1. 内容集合(Content Collections)
使用 Content Collections 管理结构化内容:
// src/content/config.ts
import { defineCollection, z } from 'astro:content';
const blog = defineCollection({
schema: z.object({
title: z.string(),
pubDate: z.date(),
tags: z.array(z.string()),
}),
});
export const collections = { blog };
2. 图片优化
Astro 内置图片优化:
---
import { Image } from 'astro:assets';
import heroImage from '../../../../assets/hero.jpg';
---
<Image
src={heroImage}
alt="Hero"
width={1200}
height={600}
format="webp"
/>
3. 部分水合策略
选择合适的水合时机:
<!-- 页面加载时立即水合 -->
<Component client:load />
<!-- 组件可见时水合 -->
<Component client:visible />
<!-- 空闲时水合 -->
<Component client:idle />
<!-- 仅在客户端渲染 -->
<Component client:only="react" />
与其他框架对比
Astro vs Next.js
| 特性 | Astro | Next.js |
|---|---|---|
| 默认 JS | 0 KB | ~100 KB |
| 水合策略 | 部分水合 | 全页水合 |
| 学习曲线 | 低 | 中 |
| 适用场景 | 内容网站 | 全栈应用 |
Astro vs Gatsby
| 特性 | Astro | Gatsby |
|---|---|---|
| 构建速度 | 快 | 慢 |
| GraphQL | 可选 | 必需 |
| 插件生态 | 成长中 | 成熟 |
实际案例
1. 文档站点
// 文档站点
- 快速的页面加载
- 出色的 SEO
- 零 JavaScript 开销
2. 博客平台
// 博客平台
- Markdown/MDX 支持
- 内置内容集合
- 优秀的开发体验
3. 营销页面
// 营销页面
- 较快的加载速度
- 较好的 Lighthouse 分数
- 可选的交互组件
性能监控
使用 Astro 内置的性能工具:
// astro.config.mjs
export default defineConfig({
output: 'static',
build: {
inlineStylesheets: 'auto',
},
vite: {
build: {
rollupOptions: {
output: {
manualChunks: (id) => {
// 自定义代码分割
},
},
},
},
},
});
结论
Astro 的零 JavaScript 默认策略和群岛架构,适合以静态内容为主、只在局部加入交互的站点,例如:
- 博客和文档站点
- 电商产品页
- 新闻和内容网站
- 作品集网站
如果项目以内容展示为主,并且重视性能、SEO 和开发体验,Astro 是一个可以纳入评估的选项。