Astro 静态网站生成:内容网站开发笔记

静态站点生成器(SSG)常用于博客、文档和内容型网站。Astro 属于这一类框架,它的重点是尽量减少发送到浏览器端的 JavaScript。

什么是 Astro?

Astro 是一个 静态网站生成器,它的基本理念是:

尽可能少地向浏览器发送 JavaScript。

主要特性

  1. 零 JavaScript 默认策略
  • 默认情况下,Astro 不向客户端发送任何 JavaScript
  • 只在需要时才加载 JavaScript
  1. 群岛架构(Islands Architecture)
  • 页面中的交互组件被隔离为「岛屿」
  • 每个岛屿独立加载和水合
  1. 框架无关
  • 支持 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

性能指标对比

指标传统 SPAAstro
FCP2-3s0.5-1s
TTI3-5s0.5-1s
Bundle Size200-500KB0-50KB
Lighthouse60-8095-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

特性AstroNext.js
默认 JS0 KB~100 KB
水合策略部分水合全页水合
学习曲线
适用场景内容网站全栈应用

Astro vs Gatsby

特性AstroGatsby
构建速度
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 是一个可以纳入评估的选项。