- PageSpeed Insights
โพสต์นี้แปลโดย AI
บทสรุปของโพสต์โดย durumis AI
- การใช้เครื่องมือวัดประสิทธิภาพเว็บไซต์ (PageSpeed Insights, Lighthouse) เพื่อปรับปรุงประสิทธิภาพเว็บไซต์จะช่วยให้เว็บไซต์ปรากฏในผลการค้นหาได้ดีขึ้น และตัวชี้วัด Web Core Vitals มีความสำคัญ
- เพื่อปรับปรุงตัวชี้วัดต่างๆ เช่น CLS, LCP, FCP และ FID เราสามารถใช้เทคนิคต่างๆ เช่น UI Skeleton, การปรับแต่งรูปภาพ, การลบองค์ประกอบที่บล็อกการแสดงผล, การปรับแต่ง Web Font, การประมวลผล JavaScript แบบอะซิงโครนัส เป็นต้น
- บทความนี้จะแนะนำวิธีการปรับปรุงตัวชี้วัดต่างๆ พร้อมทั้งแนะนำเทคนิคต่างๆ ในการเพิ่มประสิทธิภาพเว็บไซต์ (เช่น การบีบอัด gzip, Web Worker เป็นต้น) และในอนาคตจะมีการขยายเนื้อหาเพิ่มเติมในหัวข้อที่เกี่ยวข้อง
ผ่านเว็บไซต์ที่ Google ให้บริการ
สามารถวัดประสิทธิภาพของเว็บได้อย่างง่ายดาย
https://pagespeed.web.dev/
โดยป้อน URL เพื่อวัด หรือติดตั้ง Lighthouse เป็นส่วนขยายของ Chrome เพื่อวัดก็ได้
การปรับปรุงตัวชี้วัดดีอย่างไร?
สามารถแสดงผลในเครื่องมือค้นหาได้ดีขึ้น SEO มักใช้การเรนเดอร์ฝั่งเซิร์ฟเวอร์เป็นหลัก
แต่ถ้าตัวชี้วัดประสิทธิภาพข้างต้นต่ำ ผลลัพธ์ก็จะลดลงอย่างมาก
ปรับปรุงอย่างไร?
เว็บไซต์ web.dev ได้อธิบายรายละเอียดเกี่ยวกับวิธีการปรับปรุงตัวชี้วัดแต่ละตัวอย่างละเอียด
โดยเฉพาะตัวชี้วัด 3 ตัวที่มีผลต่อคะแนนมากที่สุด (Web Core Vitals)
ฉันต้องการบันทึกสิ่งที่ฉันได้ลองทำเพื่อปรับปรุงตัวชี้วัด
จะวัดในเครื่อง (local) ได้อย่างไร?
export default () => { if (process.client && 'PerformanceObserver' in window) { let cumulativeLayoutShiftScore = 0; let largestContentfulPaint = 0; let firstInputDelay = 0; let firstContentfulPaint = 0;
// CLS const clsObserver = new PerformanceObserver((list) => { const entries = list.getEntries(); entries.forEach((entry) => { if (!entry.hadRecentInput) { cumulativeLayoutShiftScore += entry.value; } }); }); // LCP const lcpObserver = new PerformanceObserver((list) => { const entries = list.getEntries(); const lastEntry = entries[entries.length - 1]; largestContentfulPaint = lastEntry.startTime; }); // FID const fidObserver = new PerformanceObserver((list) => { const entries = list.getEntries(); const firstEntry = entries[0]; firstInputDelay = firstEntry.processingStart - firstEntry.startTime; }); // FCP const fcpObserver = new PerformanceObserver((list) => { const entries = list.getEntries(); const firstEntry = entries[0]; firstContentfulPaint = firstEntry.startTime; }); clsObserver.observe({ type: 'layout-shift', buffered: true }); lcpObserver.observe({ type: 'largest-contentful-paint', buffered: true }); fidObserver.observe({ type: 'first-input', buffered: true }); fcpObserver.observe({ type: 'paint', buffered: true }); window.addEventListener('onload', () => { console.log('Final CLS Score:', cumulativeLayoutShiftScore); console.log('LCP:', largestContentfulPaint); console.log('FID:', firstInputDelay); console.log('FCP:', firstContentfulPaint); }); } };
แทรกโค้ดข้างต้น ในกรณีของ Nuxt ให้ใส่ไว้ใน plugins แล้วตรวจสอบ console log
Cumulative Layout Shift (CLS)
เป็นการวัดระดับการเปลี่ยนแปลงของเลย์เอาต์ในระหว่างการเรนเดอร์
ยกตัวอย่างเช่น สมมติว่ามีหน้าเว็บที่เรนเดอร์ภาพขนาด 400x400 โดยรับ URL ของภาพจากการตอบสนองของ API
ตำแหน่งของเลย์เอาต์บางส่วนจะเลื่อนไป 400 พิกเซล เนื่องจากการเรนเดอร์ภาพ
นี่คือการเลื่อนที่ผู้ใช้คาดไม่ถึง ซึ่งส่งผลเสียต่อ UX และเบราว์เซอร์ก็ได้รับผลกระทบทางอ้อม
ในการเรนเดอร์หน้าจอ
มีวิธีแก้ไขที่ง่ายๆ 2 วิธี
1. ใช้ UI Skeleton
- เว็บไซต์ส่วนใหญ่จะวาดโครงร่าง (Skeleton) ที่เหมาะสมกับขนาดของภาพหรือขนาดของส่วนประกอบ ในขณะที่พัฒนาหน้าจอ ให้พิจารณาส่วนนี้ด้วย ในกรณีของ Vue สามารถใช้ v-if และ v-else เพื่อวาดโครงร่างที่เหมาะสมกับแต่ละองค์ประกอบ
2. จองพื้นที่ความสูง
- หากโครงร่างมีสไตล์มากเกินไป อาจทำให้การบำรุงรักษาซับซ้อนและอาจส่งผลเสียได้ การกำหนด min-height ขององค์ประกอบที่จะเรนเดอร์ก็เพียงพอที่จะเห็นผลลัพธ์ได้แล้ว
- ในกรณีของเว็บไซต์ที่ตอบสนองต่อการใช้งาน (Responsive) เป็นต้น ขนาดของภาพจะแตกต่างกันไปตามอุปกรณ์ ดังนั้นจึงยากที่จะกำหนดความสูงแบบคงที่ ในกรณีนี้ สามารถใช้ขนาดของอุปกรณ์ที่เล็กที่สุดเป็นเกณฑ์หรือใช้ vh หรือ vw
3. ระบุ width และ height ในแท็กภาพ
- สามารถใส่ width และ height ในแท็กภาพได้ดังนี้
<img src="image.jpg" width="400" height="400">
แม้ว่าขนาดจริงของภาพจะไม่ใช่ 400x400 แต่ก็แจ้งให้เบราว์เซอร์ทราบถึงขนาดที่คาดการณ์ไว้ของภาพ
4. ใช้ font-display: swap เพื่อป้องกันการเปลี่ยนแปลงเลย์เอาต์ที่เกิดจากเว็บฟอนต์
- ระบุฟอนต์สำรองเพื่อป้องกันการเลื่อนเลย์เอาต์
Largest Contentful Paint(LCP)
คือเวลาที่ใช้ในการเรนเดอร์องค์ประกอบที่ใหญ่ที่สุดบนหน้าจอ โดยทั่วไปแล้วจะเป็นภาพ ดังนั้นการเพิ่มความเร็วในการโหลดจึงเป็นสิ่งที่เห็นได้ชัด
1. ลดขนาดของภาพ
- ตรวจสอบว่าขนาดของภาพไม่ใหญ่เกินไปเมื่อเทียบกับขนาดที่เรนเดอร์
- เพิ่มประสิทธิภาพการเรนเดอร์ภาพด้วยนามสกุล เช่น webp webp จะมีขนาดไฟล์เล็กกว่า JPEG ประมาณ 30% ในกรณีที่ใช้การบีบอัดแบบ Lossy และมีขนาดไฟล์เล็กกว่า png ประมาณ 20% ในกรณีที่ใช้การบีบอัดแบบ Lossless
- สามารถพิจารณาการโหลดแบบ Lazy Loading ซึ่งจะโหลดภาพเมื่อเลื่อนไปถึงตำแหน่งที่กำหนดได้
2. ใช้แคชหรือ CDN
3. ลบองค์ประกอบที่บล็อกการเรนเดอร์
- เนื่องจากตัวชี้วัดส่วนใหญ่ได้รับผลกระทบ ดังนั้นจึงจำเป็นต้องลบออก เบราว์เซอร์จะดึงสคริปต์ในส่วนของแท็ก head ก่อน แล้วจึงเรนเดอร์ ดังนั้นให้ตรวจสอบว่าสคริปต์ในแท็ก head (โดยทั่วไปคือสคริปต์ภายนอก) จำเป็นต้องเรนเดอร์ก่อนหรือไม่ การใช้แท็ก async และ defer จะช่วยจัดการได้ง่ายขึ้น
* ฉันจะเขียนบทความอื่นเกี่ยวกับคุณลักษณะของสคริปต์ในแท็ก head ในภายหลัง
4. ลดขนาดของบันเดิล
- นอกเหนือจากความเร็วในการเรนเดอร์ภาพแล้ว หากการส่งข้อมูลจากเซิร์ฟเวอร์ช้า ก็จำเป็นต้องปรับปรุงส่วนนี้ด้วย
หากใช้พร็อกซีเซิร์ฟเวอร์ เช่น nginx สามารถใช้การบีบอัด gzip
* ฉันจะเขียนบทความอื่นเกี่ยวกับการตั้งค่า nginx ในภายหลัง
First Contentful Paint(FCP)
หมายถึงเวลาที่เนื้อหาแรกสุดของหน้าเว็บเรนเดอร์
1. เช่นเดียวกับการลบองค์ประกอบที่บล็อกการเรนเดอร์
2. ลดขนาดของ HTML
- การใช้แท็ก div ซ้อนกันมากเกินไปจะสร้างโครงสร้างที่ซ้อนกันมากเกินไปและทำให้ขนาดไฟล์ใหญ่ขึ้น
3. เว็บฟอนต์ภายนอกอาจเป็นปัญหา ใช้ font-display: swap; เพื่อเรนเดอร์ฟอนต์เริ่มต้นก่อน
First Input Delay(FID)
หมายถึงเวลาที่เบราว์เซอร์ใช้ในการประมวลผลการป้อนข้อมูลครั้งแรก (คลิก เลื่อน ฯลฯ) ของผู้ใช้บนหน้าเว็บ บางครั้งการกดปุ่มอาจดูเหมือนไม่ตอบสนอง แต่จริงๆ แล้วอาจเป็นเพราะกำลังรอการตอบสนองของ API
1. ใช้ Async ให้ดีเพื่อไม่ให้เธรดหลักของ JavaScript ถูกผูกไว้กับงานที่หนัก
2. สามารถใช้ Web Worker เพื่อทำงานอื่นๆ นอกเหนือจากเธรดหลักได้
* ฉันจะเขียนบทความอื่นเกี่ยวกับ Web Worker ในภายหลัง
ขอจบเพียงเท่านี้เนื่องจากข้อจำกัดจำนวนอักขระ