Astro 架構概覽
Island Architecture、渲染策略與框架定位比較的完整解析
Overview##
大多數現代前端框架(React、Vue、Next.js)預設把整個頁面當成一個 JavaScript 應用程式。即使只有一個按鈕需要互動,瀏覽器仍然要下載、解析、執行整個頁面的 JS bundle。
Astro 的出發點不同:預設零 JavaScript。頁面在 build 時渲染成純 HTML,只有明確標記為互動的元件才會載入 JS。這個設計叫做 Island Architecture。
| 傳統 SPA | Astro |
|---|---|
| 整頁是一個 JS 應用 | 頁面是靜態 HTML |
| 所有元件都需要 hydration | 只有標記的元件才 hydrate |
| 首次載入 bundle 大 | JS 按需載入,首次載入極小 |
| 適合高互動應用(dashboard) | 適合內容導向網站(docs、blog) |
Note
Astro 不是要取代 React 或 Next.js——它解決的是不同的問題。如果你的網站 90% 是靜態內容、10% 需要互動,Astro 是最佳選擇。
Architecture##
Island Architecture###
Island Architecture 的核心概念:把頁面想成一片靜態 HTML 的「海洋」,上面散佈著可互動的「島嶼」。
graph TB
subgraph Page
A[Header - Static HTML]
B[Article Content - Static HTML]
C[Search Bar - React Island]
D[Sidebar - Static HTML]
E[Comment Section - Vue Island]
F[Footer - Static HTML]
end
C -->|client:load| G[Hydrate on load]
E -->|client:visible| H[Hydrate when visible]
每個島嶼獨立 hydrate,互不影響。這代表:
- Search Bar 用 React 寫,頁面載入就 hydrate
- Comment Section 用 Vue 寫,滾動到可見時才 hydrate
- 其他部分是純 HTML,完全不需要 JS
Partial Hydration###
傳統 SSR 框架(如 Next.js)的 hydration 是全頁面的——server 渲染 HTML 後,client 端要重新把整個頁面「接管」為 React 應用。這叫 Full Hydration。
Astro 使用 Partial Hydration:只 hydrate 被標記的元件,其餘保持為純 HTML。
Full Hydration(Next.js):
┌─────────────────────────────┐
│ 整頁 hydrate 為 JS 應用 │
│ ████████████████████████ │
│ ████████████████████████ │
│ ████████████████████████ │
└─────────────────────────────┘
Partial Hydration(Astro):
┌─────────────────────────────┐
│ 靜態 HTML │
│ ░░░░░░████░░░░░░░░░░░░░░ │
│ ░░░░░░░░░░░░░░░░░░░░░░░░ │
│ ░░░░░░░░░░░████████░░░░░ │
└─────────────────────────────┘
█ = JavaScript ░ = 純 HTML
Tip
Partial Hydration 最大的好處不只是效能——它讓你可以在同一個頁面混用不同框架的元件(React + Vue + Svelte),因為每個島嶼獨立運作。
Client Directives###
Client Directive 是 Astro 控制 hydration 時機的機制。沒有加 directive 的框架元件只會渲染成靜態 HTML:
---
import SearchBar from '../components/SearchBar.jsx';
import Comments from '../components/Comments.svelte';
import Analytics from '../components/Analytics.tsx';
import HeavyChart from '../components/HeavyChart.vue';
---
<!-- 無 directive:純靜態 HTML,不會載入任何 JS -->
<SearchBar />
<!-- client:load:頁面載入立即 hydrate -->
<SearchBar client:load />
<!-- client:idle:瀏覽器閒置時 hydrate(requestIdleCallback) -->
<Analytics client:idle />
<!-- client:visible:元件進入 viewport 時 hydrate(IntersectionObserver) -->
<Comments client:visible />
<!-- client:media:符合 media query 時 hydrate -->
<HeavyChart client:media="(min-width: 768px)" />
<!-- client:only:不做 SSR,純 client-side 渲染 -->
<SearchBar client:only="react" />
| Directive | 時機 | 適用場景 |
|---|---|---|
client:load | 頁面載入 | 立即需要互動(搜尋框、導航) |
client:idle | 瀏覽器閒置 | 非關鍵互動(分析、追蹤) |
client:visible | 進入 viewport | 頁面下方的元件(留言、圖表) |
client:media | 符合 media query | 僅桌面或僅行動裝置的元件 |
client:only | 只在 client 渲染 | 依賴 browser API 的元件 |
Warning
client:only 不會在 server 端渲染,SSR 階段會是空的。必須指定框架名稱(如 client:only="react"),否則 Astro 不知道用哪個 renderer。
Rendering##
Astro 支援兩種輸出模式,透過 astro.config.mjs 設定:
// astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
// 'static':預設,build 時產生靜態 HTML(SSG)
// 'server':所有頁面預設 on-demand 渲染(SSR)
output: 'static',
});
SSG(Static Site Generation)###
預設模式。所有頁面在 build 時渲染成 HTML 檔案,部署到任何靜態 hosting:
src/pages/
├── index.astro → dist/index.html
├── about.astro → dist/about/index.html
└── blog/
└── [slug].astro → dist/blog/post-1/index.html
dist/blog/post-2/index.html
適用場景:文件站、部落格、行銷網站——內容不常變動、不需要即時資料。
SSR(Server-Side Rendering)###
設定 output: 'server' 後,頁面在每次請求時渲染。需要部署到支援 server 的環境(Node.js、Cloudflare Workers 等):
// astro.config.mjs
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';
export default defineConfig({
output: 'server',
adapter: node({ mode: 'standalone' }),
});
適用場景:需要認證、個人化內容、即時資料的頁面。
混合模式(Per-Route Control)###
Astro v5 之後,不再需要 output: 'hybrid'。在任一模式下,都可以逐頁覆蓋渲染策略:
---
// 在 output: 'server' 模式下,這個頁面改為靜態預渲染
export const prerender = true;
---
<html>
<body>
<h1>這是靜態頁面</h1>
</body>
</html>
---
// 在 output: 'static' 模式下,這個頁面改為 on-demand 渲染
export const prerender = false;
---
<html>
<body>
<h1>這是動態頁面,需要 adapter</h1>
</body>
</html>
| 模式 | 預設行為 | 覆蓋方式 | 需要 Adapter |
|---|---|---|---|
static | 全部預渲染 | prerender = false 改為動態 | 有動態頁面時需要 |
server | 全部動態渲染 | prerender = true 改為靜態 | 必須 |
Note
Astro v5 移除了 output: 'hybrid',將其功能合併到 output: 'static' 中。現在只要在 static 模式下對個別頁面設定 prerender = false,就能達到之前 hybrid 的效果。
Comparison##
Astro vs Next.js vs Nuxt###
| 面向 | Astro | Next.js | Nuxt |
|---|---|---|---|
| 定位 | 內容導向網站 | 全端 React 應用 | 全端 Vue 應用 |
| 預設 JS | 零 | 全頁 bundle | 全頁 bundle |
| Hydration | Partial(Island) | Full | Full |
| UI 框架 | 多框架共存 | React only | Vue only |
| 渲染 | SSG / SSR / 混合 | SSG / SSR / ISR / PPR | SSG / SSR / ISR |
| 學習曲線 | 低(HTML 優先) | 中(React 生態) | 中(Vue 生態) |
| 最佳場景 | Docs、Blog、行銷站 | Dashboard、SaaS、電商 | Dashboard、SaaS |
選擇原則:
- 內容為主、互動為輔 → Astro(最少 JS、最快載入)
- React 生態 + 全端功能 → Next.js(API Routes、Middleware、ISR)
- Vue 生態 + 全端功能 → Nuxt(同上,Vue 版本)
- 高互動 SPA → 不需要 meta-framework,直接用 React / Vue + Vite
MPA vs SPA###
Astro 本質上是 MPA(Multi-Page Application)——每次導航是一次完整的頁面請求。這跟 SPA 的 client-side routing 不同:
| 面向 | MPA(Astro) | SPA(React / Vue) |
|---|---|---|
| 導航 | 整頁重新載入 | client-side routing |
| 首次載入 | 快(少 JS) | 慢(大 bundle) |
| 後續導航 | 較慢(重新請求) | 快(只更新 DOM) |
| SEO | 天生友好 | 需要 SSR 輔助 |
Tip
Astro 支援 View Transitions API 來實現 SPA 風格的頁面轉場效果,同時保持 MPA 的架構優勢。加上 <ViewTransitions /> 元件即可啟用。
Quiz##
Summary##
- Astro 是內容導向的 web 框架,預設零 JavaScript,只在需要時載入
- Island Architecture 把頁面拆成靜態 HTML + 可互動島嶼,每個島嶼獨立 hydrate
- Client Directives(
client:load、client:visible、client:idle等)控制 hydration 時機 - Partial Hydration 比 Full Hydration 更少 JS、更快載入,且支援多框架共存
- 兩種輸出模式:
static(SSG)和server(SSR),可逐頁覆蓋渲染策略 - Astro v5 移除
hybrid模式,混合渲染改用prerenderflag 控制 - 適合 Docs、Blog、行銷站;不適合高互動 SPA 應用
留言 (0)
登入後即可留言