Astro Island 架構筆記
什麼是 Island Architecture
Astro 的 Island Architecture 把頁面分成靜態的 HTML 海洋和可互動的 JavaScript 島嶼。預設情況下,頁面是純 HTML/CSS,只有被標記為 island 的元件才會載入 JavaScript。
這個架構對效能的影響非常直接:頁面初始載入不需要下載整個 JavaScript bundle,使用者看到內容的速度極快。互動性只在需要的地方注入。
Hydration 策略選擇
Astro 提供幾種 hydration 指令,每種適用不同場景:
| 指令 | 行為 | 本專案用途 |
|---|---|---|
client:load | 頁面載入時立即 hydrate | Hero 3D 場景、語言切換器 |
client:visible | 元件進入 viewport 時 hydrate | 知識圖譜、模型檢視器 |
client:idle | 瀏覽器閒置時 hydrate | Pagefind 搜尋 |
client:media | 符合 media query 時 hydrate | 未使用 |
選擇標準:如果元件在首屏且需要立即互動,用 client:load。如果在折疊下方,用 client:visible。如果是輔助功能(搜尋),用 client:idle。
本專案的關鍵決策
一頁一個 WebGL Context
Three.js 的 WebGLRenderer 建立 WebGL context 的成本不低。瀏覽器通常限制同時活躍的 context 數量(Chrome 約 16 個)。所以本專案嚴格遵守一頁只建立一個 WebGL context 的原則。
這意味著 Hero 3D 場景和知識圖譜不會同時存在於同一頁面。如果未來需要,會透過切換 scene 而非建立新 renderer 來解決。
GSAP 不走 Island
GSAP 的滾動動畫使用 Astro 的原生 <script> 標籤,而不是包在 island 元件裡。原因是 GSAP + ScrollTrigger 需要掌握整個頁面的 scroll 狀態,放在 island 裡反而增加複雜度。
在 View Transitions 架構下,我在 astro:page-load 初始化 Lenis + ScrollTrigger,在 astro:before-swap 時銷毀。確保每次頁面切換都重新建立乾淨的滾動狀態。
三階行動裝置偵測
透過 WEBGL_debug_renderer_info 取得 GPU 型號,結合 navigator.deviceMemory 和 prefers-reduced-motion,將裝置分為三個等級:
- High:完整 3D + 後製效果
- Medium:簡化 3D,減少粒子,無後製
- Low:2D 替代方案(d3-force 2D + CSS 動畫)
這確保了 Three.js 資源追蹤器 的負擔不會超出裝置能力。
與其他框架的比較
我在做決策前也考慮過 Next.js 和 Nuxt。但這個專案的本質是內容展示,不需要伺服器端狀態管理。Astro 的 content collections 對 MDX 的原生支援,加上靜態輸出的效能優勢,讓它成為最適合的選擇。
待觀察
- Astro 5 的 Server Islands 對本專案是否有應用場景
- View Transitions API 在行動瀏覽器的支援度進展