Performance & Zero-JS
Performance ที่เริ่มมาพร้อม ไม่ใช่มาแปะทีหลัง
หัวข้อที่มีชื่อว่า “Performance ที่เริ่มมาพร้อม ไม่ใช่มาแปะทีหลัง”framework ส่วนใหญ่ทำให้เราต้องไล่ทวง performance คืน: build app เสร็จ ปรากฏว่าช้า แล้วค่อย optimize Astro กลับด้าน — เรา เริ่ม ที่ baseline ที่เร็ว (static HTML, zero JavaScript) และงานของเราคือรักษา baseline นั้นไว้ ทุกกิโลไบต์ของ client JavaScript คืออันที่เราเพิ่มเข้าไปเอง คำถามจึงเป็น “อันนี้จำเป็นต้องส่งไปจริงไหม” เสมอ
เลือก client directive ที่ถูกที่สุด
หัวข้อที่มีชื่อว่า “เลือก client directive ที่ถูกที่สุด”บทเรียน islands พูดถึงว่า client directive ทำอะไร ตรงนี้คือมุมมองด้าน performance directive ที่เราเลือกกำหนดว่า JavaScript จะรันเท่าไรและเมื่อไร:
| Directive | ส่ง & รัน JS | ใช้เมื่อ |
|---|---|---|
client:load | ทันทีตอน page load | interactivity สำคัญ above-the-fold (พบไม่บ่อย) |
client:idle | เมื่อ browser ว่าง | interactive แต่ไม่จำเป็นต้องทันที |
client:visible | เมื่อ scroll เข้ามาในจอ | island ที่อยู่ below-the-fold (default ที่ดีที่สุด) |
client:media | เฉพาะที่ breakpoint | widget เฉพาะ mobile หรือเฉพาะ desktop |
หลักคิด: เอื้อมไปหา client:visible (หรือ client:idle) ก่อน client:load carousel ที่อยู่ลงไปสามจอไม่ต้องใช้ JavaScript ตอน load แรก การ hydrate ด้วย client:visible ทำให้ cost นั้นอยู่นอก critical path การใช้ client:load เกินจำเป็นจะแอบสร้าง cost แบบ “ทุกอย่าง hydrate ตอนแรก” ที่ Astro มีอยู่เพื่อหลีกเลี่ยงกลับมา
flowchart LR load["client:load"] --> upfront["JS on the critical path (heaviest)"] idle["client:idle"] --> later["JS after first paint"] visible["client:visible"] --> onscroll["JS only when scrolled into view (lightest)"]
Prefetch สำหรับ navigation ที่ทันที
หัวข้อที่มีชื่อว่า “Prefetch สำหรับ navigation ที่ทันที”load แรกเร็วเป็นแค่ครึ่งเรื่อง navigation ที่เร็วคืออีกครึ่ง Astro prefetch HTML ของหน้าได้ก่อนที่ user จะคลิก หน้าถัดไปจึงแทบจะทันที เปิดใน config แล้ว Astro จะ prefetch link ตอน hover หรือตอนเข้าจอให้โดย default หรือ opt in ต่อ link แบบชัดเจน:
<a href="/pricing" data-astro-prefetch>Pricing</a>พอจับคู่กับ <ClientRouter /> prefetch ทำให้ navigation แบบ multi-page รู้สึกเหมือน SPA — HTML อยู่ใน cache ของ browser แล้วตอนคลิก — โดยไม่ต้องมี data layer ฝั่ง client
วัดสิ่งที่เราส่งไปจริง
หัวข้อที่มีชื่อว่า “วัดสิ่งที่เราส่งไปจริง”อย่า optimize ด้วยความรู้สึก ดูสองอย่าง:
- island ที่เราส่งไป build เว็บแล้วเช็คว่า component ไหนกลายเป็น island จริง (และด้วย directive อะไร) component ที่คิดว่า static แต่ hydrate อยู่คือ JavaScript ที่เสียเปล่า ส่วน
client:loadที่ควรเป็นclient:visibleคือ cost ที่วางผิดที่ - Lighthouse / Core Web Vitals รัน Lighthouse (ใน Chrome DevTools) กับเว็บที่ build แล้ว จับตา Largest Contentful Paint (มักเป็น hero image — ดูบทเรียน asset), Cumulative Layout Shift (จองพื้นที่ image/font) และ Total Blocking Time (JavaScript ของ island)
baseline ของ Astro มักได้คะแนนเกือบเต็มตั้งแต่แรก เมื่อคะแนนตก สาเหตุมักเป็นหนึ่งใน: image ที่ไม่ optimize, font ที่ทำให้ shift หรือ island ที่ hydrate เร็วกว่าที่จำเป็น