← Back to Blog

Astro Islands 與 React 組件集成實踐

Astro架構

Astro 的 Islands 架構允許在靜態 HTML 中嵌入交互式的 React 組件,同時保持頁面整體的零 JS 默認輸出。本文記錄在 monorepo 環境下集成共享 React 組件的實踐心得。

什麼是 Astro Islands

Astro 默認生成純靜態 HTML,只有顯式加上 client:* 指令的組件才會水合為交互式 Island。這意味著大多數頁面組件(佈局、靜態卡片、Prose 容器)完全不需要 JS。

<!-- 靜態渲染,零 JS -->
<Card title="靜態卡片" href="/blog" />

<!-- 啟用水合,包含事件監聽器 -->
<Card client:load tilt title="交互卡片" href="/blog" />

在 pnpm Monorepo 中共享組件

packages/ui 中定義 React 組件,各 app 通過 @personal/ui 包名引入:

import { Card } from '@personal/ui/components/Card.tsx';
import { Nav }  from '@personal/ui/components/Nav.tsx';

關鍵點:@personal/ui 不需要 build 步驟,直接暴露 .tsx 源文件,由各 app 的 Vite 統一編譯。tsconfig"noEmit": true 確保包本身不輸出編譯產物。

client 指令選擇

指令時機適用場景
client:load頁面加載立即水合首屏可見的交互組件(Nav)
client:visible進入視口時水合列表中的卡片、圖表
client:idle瀏覽器空閒時水合非關鍵交互(搜索框)

常見陷阱

問題: 在 Astro 中使用帶 useState 的組件但沒加 client:*,導致事件無響應。
解決: 靜態渲染時 React hooks 不執行,必須加 client 指令。

問題: 服務端/客戶端 hydration 不一致警告。
解決: 確保組件的初始渲染不依賴 windowdocument,通過 useEffect 延遲訪問瀏覽器 API。