岛屿架构 #
一、什么是岛屿架构? #
1.1 传统架构问题 #
text
传统 SPA(单页应用):
┌────────────────────────────────────────────────────┐
│ │
│ 整个页面需要水合(Hydration) │
│ ████████████████████████████████████████████ │
│ │
│ 问题: │
│ • 大量 JavaScript 需要加载 │
│ • 首屏渲染慢 │
│ • 交互延迟 │
│ • SEO 困难 │
│ │
└────────────────────────────────────────────────────┘
1.2 Islands 架构解决方案 #
text
Astro Islands 架构:
┌────────────────────────────────────────────────────┐
│ │
│ 静态 HTML(零 JavaScript) │
│ │
│ ┌──────────┐ ┌──────────┐ │
│ │ 交互岛屿 │ │ 交互岛屿 │ │
│ │ 🏝️ │ │ 🏝️ │ │
│ │ 购物车 │ │ 搜索框 │ │
│ └──────────┘ └──────────┘ │
│ │
│ 优势: │
│ • 首屏极快 │
│ • 按需加载 JavaScript │
│ • SEO 友好 │
│ • 优秀的用户体验 │
│ │
└────────────────────────────────────────────────────┘
二、水合策略 #
2.1 client:load #
页面加载时立即水合:
astro
---
import Counter from '../components/Counter';
---
<!-- 首屏关键交互组件 -->
<Counter client:load />
适用场景:
- 首屏可见的交互组件
- 关键功能组件
- 不依赖其他条件
2.2 client:idle #
浏览器空闲时水合:
astro
---
import Newsletter from '../components/Newsletter';
---
<!-- 非关键交互组件 -->
<Newsletter client:idle />
适用场景:
- 页面底部的组件
- 非关键功能
- 可延迟加载
2.3 client:visible #
进入视口时水合:
astro
---
import ImageGallery from '../components/ImageGallery';
---
<!-- 滚动后可见的组件 -->
<ImageGallery client:visible />
适用场景:
- 需要滚动才能看到的组件
- 图片画廊
- 评论区域
2.4 client:media #
满足媒体查询时水合:
astro
---
import MobileMenu from '../components/MobileMenu';
---
<!-- 仅在移动端加载 -->
<MobileMenu client:media="(max-width: 768px)" />
适用场景:
- 响应式组件
- 特定设备功能
- 条件性交互
2.5 client:only #
跳过服务端渲染,仅在客户端渲染:
astro
---
import BrowserChart from '../components/BrowserChart';
---
<!-- 依赖浏览器 API 的组件 -->
<BrowserChart client:only="react" />
适用场景:
- 依赖 window/document 的组件
- 浏览器特定功能
- 第三方库限制
三、岛屿优化 #
3.1 最小化岛屿 #
astro
---
import StaticContent from '../components/StaticContent.astro';
import InteractiveButton from '../components/InteractiveButton';
---
<div>
<!-- 静态内容:不需要 JS -->
<StaticContent />
<!-- 只有交互部分是岛屿 -->
<InteractiveButton client:load />
</div>
3.2 拆分组件 #
astro
---
// ❌ 不好的做法:整个组件都是岛屿
<Card client:visible>
<h2>标题</h2>
<p>静态内容...</p>
<button>交互按钮</button>
</Card>
// ✅ 好的做法:只有交互部分是岛屿
<Card>
<h2>标题</h2>
<p>静态内容...</p>
<InteractiveButton client:visible />
</Card>
---
3.3 延迟加载 #
astro
---
import HeavyComponent from '../components/HeavyComponent';
---
<div>
<h1>页面标题</h1>
<!-- 首屏内容 -->
<p>首屏内容...</p>
<!-- 延迟加载重型组件 -->
<HeavyComponent client:visible />
</div>
四、性能对比 #
4.1 传统 SPA #
text
加载流程:
1. HTML 下载
2. JS 下载(大量)
3. JS 解析执行
4. 组件渲染
5. 页面可交互
首屏时间:慢
可交互时间:慢
4.2 Astro Islands #
text
加载流程:
1. HTML 下载(完整内容)
2. 页面渲染(立即可见)
3. 按需加载岛屿 JS
4. 岛屿水合
首屏时间:快
可交互时间:快
4.3 性能指标 #
| 指标 | 传统 SPA | Astro Islands |
|---|---|---|
| FCP | 慢 | 快 |
| LCP | 慢 | 快 |
| TTI | 慢 | 快 |
| JS 体积 | 大 | 小 |
五、最佳实践 #
5.1 选择正确的指令 #
text
决策流程:
是否需要交互?
├── 否 → 使用 Astro 组件(零 JS)
└── 是 → 需要何时交互?
├── 立即 → client:load
├── 空闲时 → client:idle
├── 可见时 → client:visible
└── 特定条件 → client:media
5.2 组件设计原则 #
text
1. 静态优先
- 默认使用 Astro 组件
- 只有交互部分使用框架组件
2. 最小岛屿
- 只把交互部分变成岛屿
- 静态内容保持静态
3. 延迟加载
- 非首屏组件使用 client:visible
- 非关键功能使用 client:idle
4. 条件加载
- 响应式组件使用 client:media
- 避免不必要的 JS 加载
5.3 实际案例 #
astro
---
// 博客页面示例
import Layout from '../layouts/Layout.astro';
import TableOfContents from '../components/TableOfContents.astro';
import ShareButtons from '../components/ShareButtons';
import CommentSection from '../components/CommentSection';
import Newsletter from '../components/Newsletter';
---
<Layout>
<article>
<!-- 静态内容 -->
<h1>{post.data.title}</h1>
<Content />
<!-- 分享按钮:立即交互 -->
<ShareButtons client:load />
<!-- 评论区:滚动后加载 -->
<CommentSection client:visible />
<!-- 订阅表单:空闲时加载 -->
<Newsletter client:idle />
</article>
<!-- 目录:静态 -->
<TableOfContents headings={headings} />
</Layout>
六、总结 #
岛屿架构核心要点:
text
┌─────────────────────────────────────────────────────┐
│ 岛屿架构要点 │
├─────────────────────────────────────────────────────┤
│ │
│ 🏝️ 核心概念 静态 HTML + 交互岛屿 │
│ │
│ 🚀 水合策略 load/idle/visible/media/only │
│ │
│ ⚡ 性能优势 首屏快、JS 少、体验好 │
│ │
│ 📐 设计原则 静态优先、最小岛屿、延迟加载 │
│ │
│ 🎯 最佳实践 按需选择指令、拆分组件 │
│ │
└─────────────────────────────────────────────────────┘
下一步,让我们学习 个人博客,通过实战项目巩固所学知识!
最后更新:2026-03-28