Client Directives
ในแอป React ทุก component hydrate ทันทีที่ bundle โหลด Astro ให้การควบคุมที่ละเอียด: แต่ละ island ประกาศว่าควร hydrate เมื่อใด ผ่าน client:* directive หากไม่มี directive component จะ render เป็น HTML แบบ static และไม่ส่ง JavaScript
ห้า directives
หัวข้อที่มีชื่อว่า “ห้า directives”client:load
หัวข้อที่มีชื่อว่า “client:load”Hydrate ทันทีเมื่อเพจโหลด ใช้กับ component ที่ต้องโต้ตอบได้ทันที — navigation menu, login form, widget ที่อยู่ above-the-fold
<SearchBar client:load />นี่คือ equivalent ตรงๆ ของ React component ใน Next.js page — hydrate ตอนโหลด ใช้อย่างระมัดระวัง ทุก client:load island เพิ่มให้ JS budget เริ่มต้น
client:idle
หัวข้อที่มีชื่อว่า “client:idle”Hydrate หลังจาก browser ยิง requestIdleCallback — เมื่อ main thread ว่าง ใช้กับ interactive components ที่สำคัญแต่ไม่ต้องการทันที
<NewsletterSignup client:idle />ในแอป React ไม่มี equivalent — ทุกอย่างโหลดแบบ eager client:idle คือ performance win ฟรีสำหรับ secondary widgets
client:visible
หัวข้อที่มีชื่อว่า “client:visible”Hydrate เมื่อ root element ของ component เข้ามาใน viewport (ใช้ IntersectionObserver) เหมาะสำหรับ islands ที่อยู่ below-the-fold: comment sections, carousels, interactive charts
<CommentThread client:visible /><PricingTable client:visible />ผู้ใช้ที่ไม่เลื่อนลงไปไม่มีวันดาวน์โหลด JS นี่คือ directive ที่ส่งผลมากที่สุดสำหรับเพจยาวๆ
client:media
หัวข้อที่มีชื่อว่า “client:media”Hydrate เมื่อ CSS media query ตรงกัน ใช้กับ islands ที่มีอยู่เฉพาะใน layout บางอย่าง — mobile bottom nav, desktop sidebar filter
<MobileMenu client:media="(max-width: 768px)" /><DesktopFilter client:media="(min-width: 1024px)" />ผู้ใช้ desktop ไม่เคยดาวน์โหลด JS ของ mobile component; ผู้ใช้ mobile ไม่เคยดาวน์โหลด JS ของ desktop
client:only
หัวข้อที่มีชื่อว่า “client:only”ข้าม server-side rendering ทั้งหมดและ render เฉพาะใน browser ต้องส่งชื่อ framework เป็น value ใช้กับ component ที่เรียกใช้ browser-only APIs (window, localStorage, WebGL) ที่จะ crash ระหว่าง SSR
<ThreeScene client:only="react" /><MapWidget client:only="react" />หากไม่มี
client:onlyAstro ยังรัน React component บน server เพื่อสร้าง HTML เริ่มต้น ถ้า component เรียกwindowหรือdocumentที่ top level ขั้นตอน SSR จะ throwclient:onlyข้ามขั้นตอนนั้น
ทั้งห้า directives เคียงข้างกัน
หัวข้อที่มีชื่อว่า “ทั้งห้า directives เคียงข้างกัน”// React/Next.js — no directive system.// All components hydrate on load.// Lazy loading is manual (React.lazy + Suspense).import dynamic from 'next/dynamic';
const HeavyChart = dynamic(() => import('./HeavyChart'), { ssr: false, // skip SSR — closest to client:only});
export default function Page() { return ( <> <SearchBar /> {/* eager hydration */} <HeavyChart /> {/* ssr:false ~ client:only */} {/* No built-in idle/visible/media support */} </> );}---import SearchBar from '../components/SearchBar.jsx';import NewsletterSignup from '../components/NewsletterSignup.jsx';import CommentThread from '../components/CommentThread.jsx';import MobileMenu from '../components/MobileMenu.jsx';import ThreeScene from '../components/ThreeScene.jsx';---<!-- Hydrate immediately --><SearchBar client:load />
<!-- Hydrate when browser is idle --><NewsletterSignup client:idle />
<!-- Hydrate when scrolled into view --><CommentThread client:visible />
<!-- Hydrate only on mobile --><MobileMenu client:media="(max-width: 768px)" />
<!-- Browser-only, skip SSR --><ThreeScene client:only="react" />ไม่มี directive = HTML แบบ static
หัวข้อที่มีชื่อว่า “ไม่มี directive = HTML แบบ static”สิ่งที่สำคัญที่สุดที่ต้องจำ: React component ที่ไม่มี directive คือ HTML แบบ static Astro รัน component นั้นบน server render output เป็น HTML และไม่ส่งอะไรไปยัง browser
---import ProductCard from '../components/ProductCard.jsx';---<!-- No client: directive → static HTML, zero JS --><ProductCard title="Widget" price={29} />นี่เป็นเจตนา Astro ส่งเสริมให้ถามว่า: “component นี้จำเป็นต้อง interactive จริงหรือไม่?” ถ้า React component แค่แสดงข้อมูล ก็ปล่อยให้เป็น static ได้