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

Islands กับ Client Interactivity

โมดูล Foundations วางหลักไว้แล้วว่า Astro ส่ง JavaScript เป็นศูนย์โดย default ซึ่งดีมากสำหรับ content แต่เว็บจริงก็ยังต้องมี search box, cart, ปุ่ม toggle theme, ปุ่ม like อยู่ดี โมดูลนี้คือการเพิ่ม interactivity เท่านั้น — และไม่มากไปกว่านั้น

หน่วยของ interactivity ใน Astro คือ island โดย island คือ framework component (React, Vue, Svelte, Solid, Preact) ที่เรา ตั้งใจ hydrate บน client ด้วย client directive ส่วนทุกอย่างรอบ ๆ island ยังเป็น static HTML เราไม่ได้เปลี่ยนทั้งหน้าให้กลายเป็น app แต่เลือก component แค่ตัวเดียวให้กลายเป็น interactive

flowchart TB
  page["Page: static HTML, no JS"]
  page --> header["header — static"]
  page --> search["SearchBox — island (client:load)"]
  page --> article["article — static"]
  page --> cart["Cart — island (client:visible)"]
  page --> footer["footer — static"]
หน้า static ที่มี island ถูก hydrate อยู่ไม่กี่ตัว
บทเรียนสิ่งที่จะได้เรียนรู้
Client directivesclient directive ทั้งห้าตัว (client:*) และแต่ละตัว hydrate เมื่อไหร่
Framework integrationsใช้ component ของ React/Vue/Svelte/Solid/Preact เป็น island
Sharing stateisland แยกตัวจากกัน — จะแชร์ข้อมูลข้าม island ด้วย nanostores และ slot ได้อย่างไร
Server islandsserver:defer — defer component ที่ช้าหรือ personalize โดยไม่ทำให้หน้าช้า

มีสองคำถามที่ตัดสินทุกอย่างในโมดูลนี้:

  1. component นี้ต้อง interactive จริงไหม? ถ้าไม่ ก็ปล่อยให้เป็น .astro component ธรรมดาที่ไม่ส่ง JS เลย — ที่เป็นส่วนใหญ่ของหน้า
  2. ถ้าต้อง แล้ว เมื่อไหร่ ถึงต้องกลายเป็น interactive? ทันทีเลย? ตอน scroll เข้ามาในจอ? ตอนหน้าจอขนาดหนึ่ง? คำว่า “เมื่อไหร่” นี่แหละคือสิ่งที่ client directive บอก — และเป็นความต่างระหว่างหน้าที่เร็วกับหน้าที่ช้า

ถ้าถามสองคำถามนี้ไปเรื่อย ๆ island จะเลิกเป็นกอง directive ที่งง ๆ และกลายเป็น budget แทน: ทุก island คือ JavaScript ที่เราเลือกจะส่งเอง อย่างตั้งใจ

island ใน Astro คืออะไร?
โดย default หน้าที่มี island หนึ่งตัว มี interactive JavaScript เท่าไหร่?
client directive ควบคุมอะไรเป็นหลัก?