ข้ามไปยังเนื้อหา

Server Islands

client island เป็นเรื่องของ interactivity ฝั่ง client ส่วน server islands แก้ปัญหาอีกแบบ: หน้าที่ส่วนใหญ่ cache ได้และ static แต่มีส่วนหนึ่งที่ personalize หรือช้า — avatar ของ user ที่ login อยู่, แถบ “แนะนำสำหรับคุณ”, ราคาสด ๆ ที่ต้อง query ใหม่

ถ้าไม่มี server islands คุณจะถูกบังคับให้เลือก: render ทั้งหน้าแบบ on demand (เสีย cache ของ 95% ที่ไม่เคยเปลี่ยน) หรือยอมทิ้งส่วนที่ personalize server islands ให้คุณได้ทั้งคู่ — cache เปลือก แล้ว defer ส่วนที่ dynamic

เพิ่ม directive server:defer ให้ .astro component ตัวไหนก็ได้ เพื่อเปลี่ยน component นั้นเป็น server island จากนั้น Astro จะ render ส่วนที่เหลือของหน้าทันที — โดยไม่รอ component ตัวนั้น — แล้ว HTML จริงของ component ที่ defer ไว้จะถูกดึงมาแยกต่างหากและสลับเข้ามาเมื่อพร้อม

---
import Avatar from '../components/Avatar.astro';
---
<Avatar server:defer />

HTML เริ่มต้นของหน้าออกทันทีและ cache ที่ edge ได้ ส่วน Avatar render บน server — จึงอ่าน cookie, session หรือ database ได้อย่างปลอดภัย — แต่ทำ นอกรอบ บน request ของตัวเอง หลังจากเปลือกอยู่บนจอแล้ว

เพราะ content จริงมาช้ากว่าเล็กน้อย คุณจึงใส่ fallback content ให้แสดงระหว่างรอ — skeleton, spinner หรือ placeholder กลาง ๆ — ด้วย slot="fallback":

---
import Avatar from '../components/Avatar.astro';
import GenericAvatar from '../components/GenericAvatar.astro';
---
<Avatar server:defer>
<GenericAvatar slot="fallback" />
</Avatar>

GenericAvatar render เข้าไปในเปลือกที่ cache ไว้ทันที ส่วน Avatar ที่ personalize จะเข้ามาแทนเมื่อ server render ของตัวเองส่งกลับมา

flowchart TB
  req["request the page"] --> shell["server renders shell instantly (cacheable)"]
  shell --> fb["fallback shown in place of the island"]
  fb --> fetch["browser fetches the deferred island"]
  fetch --> srv["island renders on the server (cookies, session, db)"]
  srv --> swap["real HTML swapped in over the fallback"]
หน้าออกพร้อม fallback แล้วดึง island ที่ defer มาสลับใส่

server islands เป็นเครื่องมือที่ใช่เมื่อหน้าหนึ่ง cache ได้ ยกเว้นส่วน dynamic เล็ก ๆ:

  • หน้า marketing หรือหน้าสินค้าที่เหมือนกันสำหรับทุกคน ยกเว้น คำทักทายที่ personalize หรือ cart
  • หน้าที่ส่วนใหญ่ static แต่มี query ที่ ช้า อยู่หนึ่งอันที่คุณไม่อยากให้บล็อก first paint
  • ส่วน auth-gated บนหน้าที่เป็น public และ CDN-cache

จำไว้สองอย่าง อย่างแรก server:defer render บน server จึงต้องติดตั้ง adapter (Cloudflare, Node, Vercel…) — เงื่อนไขเดียวกับ on-demand rendering ทุกแบบ ถ้าไม่มีจะเจอ error “an adapter is required” อย่างที่สอง ไม่ใช่สำหรับ client interactivity — ถ้าส่วนนั้นต้องตอบสนอง click นั่นคือ client island (client directive) อาจต้องใช้เพิ่มเติม server island เป็นเรื่องของการ defer output ที่ render บน server ไม่ใช่การ hydrate JavaScript

server:defer ทำอะไร?
use case หลักของ server island คืออะไร?
จะแสดงอะไรระหว่างที่ component server:defer กำลังโหลด?
server island ต้องมีอะไรถึงจะรันได้?