Toggle for side bar
Logo

ไหนลองมาวัด Performance ของเว็บไซต์หน่อยซิ... (1)

updated at: 11 Nov 2023

หลาย ๆคนก็คงอยากรู้ performance ของเว็บไซต์ตัวเองว่าเป็นอย่างไร (ใช่ไหมนะ ใช่ไหมนะ) ผมก็เป็นหนึ่งในนั้นแหละ และเพื่อการนั้น เราลองมาทำความเข้าใจกับมันไปพร้อมกันดีกว่า รวมถึงว่าผมได้ทำการปรับปรุงเว็บไซต์อย่างไรเพื่อทำให้เว็บไซต์นี้มี performance ที่ดีขึ้น

มันคืออะไรและสำคัญอย่างไร?

สิ่งที่สำคัญของการพัฒนาเว็บไซต์นอกจากเนื้อหาและฟีเจอร์นั่นก็คือ performance ของเว็บไซต์นั่นเอง และเพื่อให้สามารถวัดมันออกมาได้นั้น ก็จำเป็นจะต้องมีการกำหนดวิธีและเมตริกต่าง ๆขึ้นมา ซึ่งทาง Google ก็ได้คิดสิ่งที่เรียกว่า Core Web Vitals ขึ้นมาเพื่อกำหนด metric และ algorithm ต่าง ๆที่เกี่ยวกับการวัด performance ของเว็บไซต์ขึ้นมา และที่สำคัญก็คือทาง Google ก็ได้ประกาศอย่างเป็นทางการว่าลำดับของผลลัพธ์ของการค้นหาในเว็บไซต์ Google นั้นก็มีการใช้ผลลัพธ์จากการวัด performance ด้วยหลักการของ Core Web Vitals เป็นหนึ่งในปัจจัยในการจัดลำดับด้วย แต่ก่อนอื่นผมอยากให้เข้าใจก่อนว่าการวัด performance ของเว็บไซต์นั้นขึ้นอยู่กับผู้ที่กำหนดกฎเกณฑ์ในการวัด ซึ่งจริง ๆแล้วนั้นบนโลกใบนี้ก็มีกฎเกณฑ์ที่ถูกสร้างขึ้นมาหลากหลาย ดังนั้นเราต้องจึงต้องเลือกกณเกณฑ์ที่เกี่ยวข้องกับเป้าหมายของเรามากที่สุด และเนื่องจากผมต้องการที่จะให้ความสำคัญกับลำดับของผลลัพธ์การค้นหาในเว็บไซต์ Google ผมจึงเลือกศึกษา Core Web Vitals และจะทำการปรับปรุง performance ของเว็บไซต์โดยตั้งอยู่บนกฎเกณฑ์นี้

อะไรคือ Core Web Vitals?

ถ้าจะสรุปสั้น ๆง่าย ๆ มันก็คือเมตริกต่าง ๆที่ใช้สำหรับวัด performance ของเว็บไซต์ ที่ทาง Google ได้กำหนดขึ้นมา และได้มีการพัฒนามาอย่างต่อเนื่องจนถึงปัจจุบันและต่อไปยังอนาคต (เป็น Present Perfect Continuous Tense) หมายความว่าเมตริกที่ถูกกำหนดขึ้นอาจจะมีการปรับปรุง เปลี่ยนแปลง หรือถูกแทนที่ด้วยเมตริกอื่นได้ ดังนั้นเราในฐานะผู้พัฒนาเว็บไซต์ก็ควรที่จะต้องคอยอัพเดทความรู้ตามไปด้วยอยู่ตลอด (ซึ่งมันก็ไม่น่าจะมีปัญหาอะไร มันเป็นนิสัยของพวกเราอยู่แล้ว... ใช่ไหมนะ ใช่ไหมนะ)

สำหรับเมตริก ณ ปัจจุบัน (8 ตุลาคม 2023) ของ Core Web Vitals นั้น จะมีอยู่ด้วยกัน 3 อย่างได้แก่

  1. LCP (Largest Contentful Paint) - เมตริกนี้จะเป็นหน่วยของเวลา ความหมายของมันคือตั้งแต่ที่หน้าเพจเริ่มโหลด จนถึงเวลาที่เนื้อหาที่มีขนาดใหญ่ที่สุดของหน้าเพจนั้นถูก render จนเสร็จ (ขนาดใหญ่ที่สุดหมายถึง pixels ไม่ใช่ bytes) ส่วนใหญ่แล้วก็จะเป็นพวกรูปภาพต่าง ๆ
  2. CLS (Cumulative Layout Shift) - มันคือเมตริกความ "กึ้ก ๆ" ของหน้าเพจ (ห้าห้าห้า) หรือก็คือการเคลื่อนตำแหน่งหรือขนาดของ elements ต่าง ๆในหน้าโดยที่ผู้ใช้งานไม่ต้องการ ให้ลองนึกภาพว่าเวลาเราเข้าเว็บมาแล้วเห็นปุ่มอยู่ตรงกลาง แล้วพอเราจะจด ปุ่มมันดันเลื่อนลงไปข้างล่างเพราะมันมีรูปภาพที่อยู่ด้านบนปุ่มมันเพิ่งโหลดเสร็จแล้วค่อยมาแสดงผลทีหลัง ทำให้เรากดไม่โดนปุ่ม แบบนี้เราในฐานะผู้ใช้งานก็จะรู้สึกหงุดใช่ไหมครับ นั่นเลยเป็นที่มาของเมตริกนี้เพื่อให้ผู้พัฒนาลดการเคลื่อนตำแหน่งหรือขนาดของสิ่งต่าง ๆในหน้าเว็บไซต์โดยที่ผู้ใช้งานไม่ต้องการให้ได้มากที่สุด สำหรับหน่วยวัดนี้ก็จะเป็นตัวเลขอย่างเดียว เช่น 0.052, 0.126, 1.635
  3. FID (First Input Delay) - สิ่งที่ถูกวัดนั่นก็คือ delay time ของ input แรกของผู้ใช้งานเว็บไซต์ เช่น การคลิก การกดแป้นคีย์บอร์ด ฯลฯ สำหรับ input event บางอย่างอาจจะไม่ถูกนำมาคิด เช่น การเลื่อน mouse scroll เมื่อผู้ใช้งานทำอะไรบางอย่างกับเว็บไซต์แต่เว็บไซต์ตอบสนองช้า ผู้ใช้งานก็คงรู้สึกหงุดหงิดเพราะไม่ทันใจ ซึ่งจังหวะที่มักจะเกิดการ delay ก็คือช่วงแรก ๆที่ผู้ใช้งานเข้ามายังเว็บไซต์ เนื่องจากจะเป็นช่วงที่เว็บไซต์ต้องทำการ initialize/execute JavaScript หลัก ซึ่งเว็บไซต์ก็อาจจะต้องทำงานเหล่านั้นให้เสร็จก่อนจะไปทำงานอย่างอื่นให้กับผู้ใช้งาน ดังนั้นการทำสิ่งที่ทำให้ initialization/execution time ในช่วงแรกให้น้อยลง เช่น การลดขนาด bundle size ของ JavaScript เพื่อให้ไฟล์ถูกดาวน์โหลดได้เร็วขึ้น จะได้ทำการ execute ต่อได้เร็วขึ้น, การโยกโค้ดที่ไม่จำเป็นต้องถูก execute ในจังหวะแรกออกไป (Code Spliting, async/defer Script, ฯลฯ), การใช้ Web Workers เพื่อลดงานใน Browser Main-Thread ฯลฯ ก็จะช่วยทำให้ FID นี้มีระยะเวลาที่น้อยลง และยังอาจจะส่งผลในมุมอื่น ทำให้ performance โดยรวมของเว็บไซต์นั้นดีขึ้นอีกด้วย
  4. INP (Interaction to Next Paint) - เอ๊ะ ไหนบอกว่ามี 3 ทำไมมีเมตริกที่ 4 เพิ่มมาด้วยหละ?... จริง ๆแล้ว INP นั้นเป็นเมตริกที่จะมาแทนที่ FID ในอนาคต (มีนาคม 2024) ดังนั้นจึงควรที่จะศึกษาเพื่อเตรียมพร้อมไว้ก่อน สำหรับเมตริกนี้จะเป็นการวัด delay time ของ input เหมือนกับ FID แต่จะต่างกันตรงที่ INP จะพิจารณาจาก interaction ของผู้ใช้งานตลอดการใช้งานหน้าเว็บไซต์นั้น ๆ ถ้าเปรียบเมตริกเหล่านี้กับความรัก FID นั้นก็จะเสมือนเป็นเมตริกที่วัด "First Impression" ส่วน INP ก็จะเป็นเมตริกที่วัด "Long Term Relationship" นั่นเอง

พอเข้าใจคร่าว ๆแล้ว งั้นมาลองวัด performance ของเว็บไซต์นี้กัน

จากที่ได้อธิบายไปเบื้องต้น สิ่งที่เราต้องการนั่นก็คือเครื่องมือที่จะใช้วัด โดยต้องรองรับการวัดด้วยเมตริกของ Core Web Vitals ซึ่งจริง ๆแล้วก็มีอยู่หลายตัว (สามารถค้นหาจากอากู๋ได้เลยครับ มีหลายตัวจริง ๆ) โดยผมจะเลือกใช้ PageSpeed Insights เนื่องจากมันสามารถวัดอย่างอื่นที่สำคัญเช่น SEO ได้ด้วย และที่สำคัญคือใน Google Search Console ก็แนะนำให้ใช้ตัวนี้ (มี bias นิดหน่อย ฮ่าฮ่าฮ่า)

เราลองมาดูหน้าตาของมันคร่าว ๆกันดีกว่า (ขออภัยในความเบลอของรูป เอาแค่ให้พอดูรู้เรื่องก็พอเนอะ ไม่ต้องคมชัดมาก คุณจะได้ประหยัด internet bandwidth ด้วย)

PageSpeed Insights - Home Mobile

PageSpeed Insights - Home Desktop


จะเห็นว่ามันจะแบ่งออกเป็น 2 ส่วนได้แก่ คะแนนสำหรับ Mobile และสำหรับ Desktop และจะมีหัวข้อหลักอยู่ 4 หัวข้อได้แก่ Performance, Accessibility, Best Practices และ SEO และแน่นอนว่าผมจะพูดถึงเฉพาะหัวข้อ Performance เท่านั้น (ก็บล็อกนี้มันเรื่อง Performance นี่เนอะ) แต่ผมขอแนะนำว่าให้ทุกท่านลองไปลองเล่นลองใช้งานมันและให้ดูส่วนอื่น ๆที่ผมอาจจะไม่ได้พูดถึงด้วยนะ เพราะมันค่อนข้างมีประโยชน์ต่อการพัฒนาและปรับปรุงเว็บไซต์ของเรา
*ถ้าสังเกตจากในรูปจะเห็นว่ามันขาดบางเมตริกของ Core Web Vitals ไป นั่นเป็นเพราะว่าบางเมตริกนั้นต้องใช้ข้อมูลจากผู้ใช้งานจริง ๆไม่สามารถวัดผลจากในแล็บได้ เช่น FID ซึ่งถ้ามีผู้ใช้งานเว็บไซต์ (ด้วย Chrome browser) น้อยเกินไปมันก็จะไม่แสดงผลลัพธ์ออกมาให้เห็น ดังนั้นถ้าอยากรู้ว่า FID ของเว็บไซต์นี้เป็นยังไงก็ขอฝากช่วยกันแชร์ให้คนเข้ามากันเยอะ ๆนะครับ แหะ ๆ
*เกณฑ์การให้คะแนนนั้นสามารถมีการเปลี่ยนแปลงได้ตลอด ref

เอาหล่ะ! มาเริ่ม optimize เว็บไซต์กัน

รูปภาพด้านบนจะเป็นรีพอร์ตของหน้า Home เท่านั้น ดังนั้นผมเลยจะขอแปะรีพอร์ตของหน้า Blog ให้ได้เห็นด้วย เพื่อที่เราจะได้เห็นผลและปัญหาในเว็บไซต์ที่ครอบคลุมมากยิ่งขึ้น

PageSpeed Insights - Blog Mobile


PageSpeed Insights - Blog Desktop


(มันแลแดง ๆเนอะ คิดว่างั้นมั้ย 😂)
จะเห็นว่าเมตริกที่มีปัญหานั้นได้แก่ LCP, CLS และ Total Blocking Time (TBT) ซึ่ง TBT นั้นเป็นเมตริกที่บอกว่า Browser Main-Thread นั้นถูกบล็อคนานแค่ไหน อาจส่งผลให้เว็บไซต์เกิดอาการหน่วง, จอขาวนาน, ฯลฯ และอาจทำให้ interaction ระหว่างเว็บไซต์กับผู้ใช้งานมีอาการหน่วงซึ่งนั่นก็เป็นส่วนที่ทำให้ FID แย่ลงตามไปด้วย อาจจะบอกได้ว่า TBT นั้นแปรผันตรงกับ FID ก็ได้ ดังนั้นเราก็จะสามารถใช้ผลของ TBT อ้างอิงแทน FID ได้ในระดับหนึ่ง การทำให้ผลของ TBT ดีขึ้นก็จะทำให้ FID นั้นดีขึ้นตามไปด้วย

ก่อนที่จะเริ่มทำการ optimize ก็อยากจะแนะนำให้รู้จักกับ Lighthouse โดยมันคือเครื่องมือที่เว็บไซต์ PageSpeed Insights นั้นใช้นั่นแหละ และจริง ๆแล้วเราก็สามารถใช้มันผ่าน Chrome DevTools ได้ด้วย ซึ่งนี่ก็เป็นเรื่องที่ดีเพราะเราจะได้ไม่ต้อง deploy เว็บไซต์ของเราทุกครั้งที่ลอง optimize ดังนั้นผมก็จะทำการลอง optmize และทดสอบด้วยการใช้งาน Lighthouse บนเครื่องของตัวเองให้เสร็จเรียบร้อยก่อน จากนั้นจึงค่อย deploy ไปที่เซิร์ฟเวอร์ทีเดียว แล้วจากนั้นจึงทำการทดสอบบนเว็บไซต์ PageSpeed Insights เพื่อคอนเฟิร์มผลลัพธ์ แบบนี้ก็จะช่วยประหยัดเวลาที่เราต้อง deploy ถี่ ๆไปได้พอสมควร

เริ่มจากการลด Layout Shift

จากที่ผมตรวจสอบมาทั้งจากรีพอร์ทที่จะมีบอกว่าจุดไหนที่มีปัญหาเรื่อง layout shift และจากที่ทดสอบอะไรหลาย ๆอย่างก็ได้ข้อสรุปว่า ปัญหามันอยู่ที่ "รูปภาพ" ในหน้านั้น ๆ โดยปัญหาก็คือ "browser มันไม่รู้ว่าต้องใช้พื้นที่ขนาดเท่าไหร่สำหรับแสดงผลรูปภาพในจังหวะแรก" เมื่อมันไม่รู้ มันจึงไม่สามารถสงวนพื้นที่ส่วนนั้น ๆไว้สำหรับรูปภาพได้จนกว่ารูปภาพจะถูกดาวน์โหลดและแสดงผล ดังนั้นสิ่งที่จะเกิดขึ้นคือเมื่อมันดาวน์โหลดรูปภาพเสร็จและเอามาแสดงผล เนื้อหาด้านล่างรูปภาพนั้น ๆก็จะ "ถูกดันลง" ทำให้เกิด layout shift นั่นเอง... ดังนั้นงานของผมก็คือ "การทำให้ browser มันรู้ว่าต้องสงวนพื้นที่ไว้ขนาดเท่าไหร่สำหรับรูปภาพนั้น ๆ"

ผมได้ไปเจอ บทความนี้ ซึ่งได้อธิบายวิธีจัดการกับ layout shift ได้ค่อนข้างดี และโดยสรุปก็ได้วิธีการที่เหมาะสมสำหรับเคสที่เจอมาซึ่งก็คือการใส่ attribute ที่ชื่อว่า "width" และ "height" ให้กับ img tag ซึ่งการใส่สองสิ่งนี้ จะทำให้ browser (ที่นิยมใช้กันและเป็นเวอร์ชันใหม่ ๆ) รู้ขนาดพื้นที่ที่ใช้แสดงรูปภาพได้
ตัวอย่าง:

<img src="[URL]" alt="[TEXT]" width="700" height="762">

หลายคนอาจจะสงสัยว่าการกำหนด width และ height ให้กับรูปภาพแบบนี้ รูปภาพจะไม่เป็น responsive รึปล่าว จริง ๆแล้วขนาดของรูปภาพนั้นไม่ได้ขึ้นอยู่กับ attributes พวกนี้เพียงอย่างเดียว เราสามารถใช้การกำหนด style attribute หรือการใช้ CSS ในการจัดการกับขนาดของรูปภาพได้อีกที ซึ่งสิ่งที่ผมต้องการสำหรับการใส่ width และ height ในที่นี้จริง ๆคือผมต้องการให้ browser มันทำการกำหนด default aspect ratio ให้กับรูปภาพนั่นเอง ซึ่งกฎก็คือถ้ารูปภาพมี attribute ทั้ง width และ height แล้ว browser ก็จะสามารถกำหนดอัตราส่วนของพื้นที่ที่จะใช้แสดงรูปภาพได้ (เสมือนว่าเราใช้ CSS aspect-ratio นั่นเอง) เมื่อมีอัตราส่วนแล้ว เราก็จะกำหนดแค่ขนาดของด้านใดด้านหนึ่งได้ ส่วนอีกด้านหนึ่งก็ให้มันกำหนดให้ตามอัตราส่วนโดยอัตโนมัติ ดังนั้นสิ่งที่ผมจะทำต่อไปก็คือการกำหนด CSS เพื่อให้รูปภาพมันเป็น responsive ดังนี้:

img {
    max-width: 100%;
    height: auto;
}
  • max-width: 100%;: อันดับแรก ผมจะทำการกำหนดความกว้างที่มากที่สุดให้กับ img tag เป็น 100% ของ container ดังนั้นรูปภาพของผมก็จะไม่มีทางเกินกว่าขนาดของ container (หรือ parent element) ที่ตัวมันเองอยู่ หมายความว่าเริ่มต้นรูปภาพก็จะมีความกว้างตามที่กำหนดไว้ในตอนแรกด้วย width attribute แต่ถ้ามันใหญ่กว่าความกว้างของ container มันก็จะถูกลดให้เท่ากับ container นั่นเอง และเนื่องจากผมวาง layout ของหน้าให้ browser สามารถคำนวณขนาดความกว้างของมันได้ตั้งแต่แรก (ขออภัยที่ไม่ได้อธิบายว่าทำยังไงเพราะเดี๋ยวมันจะยาวเกินไป) ดังนั้น browser จึงสามารถกำหนดความกว้างของพื้นที่แสดงผลรูปภาพได้ตั้งแต่แรก ไม่จำเป็นต้องรอให้ดาวน์โหลดรูปภาพเสร็จและนำมาแสดงผล
  • height: auto;: ผมทำการเปลี่ยนขนาดของความสูงโดยให้มันถูกคำนวณใหม่แทนที่จะเป็นการ fix ค่าตามที่กำหนดให้ในตอนแรก ซึ่งถ้ามีการกำหนดอัตราส่วนไว้และมีขนาดของด้านกว้างแล้ว (ตามที่ได้อธิบายไปด้านบน) ด้วยการใช้ CSS นี้ browser ก็จะสามารถกำหนดขนาดความสูงให้มันได้โดยอัตโนมัติ
มาถึงตรงนี้ ผมก็ได้ทำให้ browser มันรู้พื้นที่ที่มันต้องสงวนเอาไว้แสดงผลรูปภาพเรียบร้อยแล้ว ถ้าอย่างนั้น เรามาลองดูผลลัพธ์กัน!

แก้ไปได้หนึ่งปัญหา 🎉 กำลังใจเริ่มมาละ! โอเคงั้นเราไปต่อกันเลยดีกว่าา
*FYI: จริง ๆแล้วผมไม่ได้เขียนโค้ดแบบตรงไปตรงมาตามที่แสดงให้ดูซะทีเดียวครับ เพราะผมไม่ได้เขียน pure HTML/CSS ดังนั้นมันเลยมีหลาย ๆอย่างครอบอยู่เช่น Framework, CSS Library ฯลฯ ซึ่งหลาย ๆคนก็คงเป็นแบบนั้นเช่นกัน ดังนั้นผมจึงอธิบายในรูปแบบของ pure HTML/CSS เพื่อให้ทุกคนได้เห็นภาพและเข้าใจตรงกันครับ ในส่วนของวิธีการจริง ๆที่ใช้ ผมอาจจะยกไปเล่าในบล็อกอื่น ๆอีกที



...สามารถอ่านต่อได้ ที่นี่