Category: guide
Core Web Vitals — ทำ Static Site ให้ได้คะแนนสูง
แนวทางปรับ LCP, CLS, INP สำหรับ static site บน Astro ที่ทำได้จริงโดยไม่ต้องจ้างผู้เชี่ยวชาญ
สารบัญ
ทำไม Core Web Vitals ถึงสำคัญ
Google ใช้ Core Web Vitals เป็น ranking signal ตั้งแต่ปี 2021 ยิ่งไปกว่านั้น ตัวเลขพวกนี้สะท้อนประสบการณ์ผู้ใช้ตรงๆ ถ้า LCP ช้า คนจะออกก่อนที่หน้าจะโหลดเสร็จ
3 Metrics หลัก
| Metric | ย่อมาจาก | วัดอะไร | เป้าหมาย |
|---|---|---|---|
| LCP | Largest Contentful Paint | ความเร็วของ element ที่ใหญ่สุด | ≤ 2.5s |
| CLS | Cumulative Layout Shift | การขยับ layout โดยไม่ตั้งใจ | ≤ 0.1 |
| INP | Interaction to Next Paint | ความเร็วตอบสนองต่อ interaction | ≤ 200ms |
LCP — ทำให้ไวขึ้น
1. Preload รูปภาพ Hero
<link rel="preload" as="image" href="/hero.jpg" fetchpriority="high" />
ใน Astro:
<Fragment slot="head">
<link rel="preload" as="image" href="/og-image.svg" fetchpriority="high" />
</Fragment>
2. ใช้ font-display: swap
@font-face {
font-family: 'Inter';
font-display: swap; /* แสดง fallback font ก่อน แล้วสลับเมื่อโหลดเสร็จ */
src: url('/fonts/inter.woff2') format('woff2');
}
3. Self-host ฟอนต์แทน Google Fonts
Google Fonts เพิ่ม round-trip HTTP เสมอ ดาวน์โหลดและ host เองจะเร็วกว่า:
# ใช้ fontsource ใน npm ecosystem
npm install @fontsource/inter
---
import '@fontsource/inter/400.css';
import '@fontsource/inter/700.css';
---
4. ปรับขนาด image ให้พอดี
<img
src="/hero.jpg"
width="1200"
height="630"
loading="eager"
decoding="async"
alt="..."
/>
ระบุ width และ height เสมอเพื่อกัน CLS ด้วย
CLS — ป้องกัน Layout Shift
สาเหตุหลัก
- รูปไม่มี dimension — เบราว์เซอร์ไม่รู้จะจองพื้นที่เท่าไหร่ก่อนโหลด
- ฟอนต์ swap ทำให้ขนาดข้อความเปลี่ยน — ใช้
size-adjustCSS descriptor แก้ได้ - Ads/embeds ที่ไม่มี placeholder
แก้ด้วย aspect-ratio
/* แทน width/height บน img โดยตรง */
.hero-image {
aspect-ratio: 16 / 9;
width: 100%;
object-fit: cover;
}
ระวัง Custom Font FOUT
@font-face {
font-family: 'Inter';
font-display: optional; /* ถ้าโหลดไม่ทันใน 100ms ใช้ fallback ไปเลย — CLS = 0 */
}
INP — ปรับ Interaction
INP แทน FID ตั้งแต่ March 2024 วัดทุก interaction ไม่ใช่แค่ first click
หลักการ
- Event handler ควรเสร็จภายใน 50ms
- งานหนักให้ยก offload ไปใน
setTimeoutหรือ Web Worker - ใช้
content-visibility: autoกับ sections ที่อยู่ล่าง fold
/* Browser จะ skip rendering ของ section ที่ไม่ได้อยู่ในหน้าจอ */
.long-section {
content-visibility: auto;
contain-intrinsic-size: 0 500px; /* estimate size เพื่อกัน scrollbar กระโดด */
}
วัดผลด้วย Tools
# ใช้ Lighthouse CLI
npm install -g lighthouse
lighthouse https://panupongws.com --view
# หรือใช้ PageSpeed Insights
# https://pagespeed.web.dev/
Astro-specific Tips
Astro ทำหลายอย่างให้อัตโนมัติแล้ว:
- Zero JS by default — ไม่มี hydration overhead เหมือน React/Vue
- Built-in CSS bundling — CSS ถูก inline ใน
<head>อัตโนมัติ - Static HTML — ไม่ต้องรอ JS parse ก่อน render
<Image />component — auto-resize, WebP conversion, lazy loading
เพิ่มเติมที่ต้องทำเอง: self-host fonts, preload hero image, ระบุ width/height บนทุก <img>