The Own Lab The Own Lab

Astro 架構概覽

Island Architecture、渲染策略與框架定位比較的完整解析

Overview##

大多數現代前端框架(React、Vue、Next.js)預設把整個頁面當成一個 JavaScript 應用程式。即使只有一個按鈕需要互動,瀏覽器仍然要下載、解析、執行整個頁面的 JS bundle。

Astro 的出發點不同:預設零 JavaScript。頁面在 build 時渲染成純 HTML,只有明確標記為互動的元件才會載入 JS。這個設計叫做 Island Architecture

傳統 SPAAstro
整頁是一個 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###

面向AstroNext.jsNuxt
定位內容導向網站全端 React 應用全端 Vue 應用
預設 JS全頁 bundle全頁 bundle
HydrationPartial(Island)FullFull
UI 框架多框架共存React onlyVue only
渲染SSG / SSR / 混合SSG / SSR / ISR / PPRSSG / 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##

Single Choice

Astro 的 Island Architecture 核心概念是什麼?

Single Choice

以下哪個 client directive 會在元件進入 viewport 時才 hydrate?

Single Choice

Astro v5 之後,如何在 static 模式下讓特定頁面使用 SSR?

Single Choice

Astro 的 Partial Hydration 相比 Next.js 的 Full Hydration 最大的優勢是什麼?

Single Choice

以下哪個場景最適合使用 Astro?

Summary##

  • Astro 是內容導向的 web 框架,預設零 JavaScript,只在需要時載入
  • Island Architecture 把頁面拆成靜態 HTML + 可互動島嶼,每個島嶼獨立 hydrate
  • Client Directives(client:loadclient:visibleclient:idle 等)控制 hydration 時機
  • Partial Hydration 比 Full Hydration 更少 JS、更快載入,且支援多框架共存
  • 兩種輸出模式:static(SSG)和 server(SSR),可逐頁覆蓋渲染策略
  • Astro v5 移除 hybrid 模式,混合渲染改用 prerender flag 控制
  • 適合 Docs、Blog、行銷站;不適合高互動 SPA 應用

留言 (0)

登入後即可留言