ในเดือนพฤษภาคม 2022 ทีม Aurora และ Angular ได้ประกาศว่าจะทำงานร่วมกันในคำสั่งเกี่ยวกับรูปภาพสำหรับ Angular เมื่อเร็วๆ นี้ คำสั่งนี้เพิ่งเปิดตัวสำหรับเวอร์ชันตัวอย่างสำหรับนักพัฒนาซอฟต์แวร์ที่เป็นส่วนหนึ่งของ Angular v14.2 โพสต์นี้กล่าวถึงวิธีที่คำสั่งรูปภาพใหม่ "NgOptimizedImage
" รองรับการเพิ่มประสิทธิภาพรูปภาพใน Angular
ที่มา
รูปภาพเป็นองค์ประกอบที่พบได้บ่อยและสำคัญต่อประสบการณ์ของผู้ใช้เว็บ โดย 99.9% ของหน้าเว็บสร้างคำขอรูปภาพอย่างน้อย 1 รูป นอกจากนี้ รูปภาพยังเป็นปัจจัยที่มีนัยสำคัญมากที่สุดในการกำหนดน้ำหนักหน้าเว็บ โดยมีค่ามัธยฐานอยู่ที่ 982 กิโลไบต์ต่อหน้า
เนื่องจากจำนวนและขนาดมีจำนวนมากขึ้น รูปภาพอาจขัดขวางประสิทธิภาพของหน้าเว็บและส่งผลต่อเมตริก Core Web Vitals สำหรับ 79.4% ของหน้าเว็บบนเดสก์ท็อป รูปภาพคือองค์ประกอบ Largest Contentful Paint (LCP) ในปี 2021 การตามหารูปภาพที่ปรับแต่งแล้วเป็นแรงผลักดันสำหรับพวกเราหลายคนอย่างต่อเนื่อง
ทีม Aurora เชื่อมั่นในการใช้ประโยชน์จากประสิทธิภาพของเฟรมเวิร์กเพื่อมอบโซลูชันที่ครอบคลุมสำหรับความท้าทายที่พบได้ทั่วไปของนักพัฒนาซอฟต์แวร์ บริษัทแรกที่เข้าไปยังพื้นที่การเพิ่มประสิทธิภาพรูปภาพคือคอมโพเนนต์รูปภาพของ Next.js พวกเขาถือว่าคอมโพเนนต์นี้เป็นพื้นที่ทดลองว่าการปรับปรุงประสบการณ์ของนักพัฒนาซอฟต์แวร์ (DX) ในการเพิ่มประสิทธิภาพรูปภาพจะช่วยให้แอปจำนวนมากขึ้นใช้เฟรมเวิร์กมีประสิทธิภาพที่ดีกว่าหรือไม่
ผลการค้นหาชุดแรกจากผู้ใช้ Next.js อย่าง Leboncoin น่าสนับสนุน Leboncoin ได้รับ LCP เพิ่มขึ้นอย่างมาก (จาก 2.4 เป็น 1.7 วินาที) หลังจากเริ่มใช้ next/image
การนำ next/image
มาใช้ในภายหลังในชุมชนมีบทบาทต่อการเพิ่มต้นทาง Next.js ที่เป็นไปตามเกณฑ์ LCP ไม่นานมานี้ก็มีคำขอสำหรับฟีเจอร์ที่คล้ายกันในเฟรมเวิร์กอื่นๆ ซึ่งหนึ่งในนั้นคือ Angular
ด้วยเหตุนี้ Aurora จึงได้ปรึกษากับ Angular และ Nuxt เพื่อสร้างต้นแบบคอมโพเนนต์รูปภาพสำหรับเฟรมเวิร์กเหล่านี้ คอมโพเนนต์รูปภาพ Nuxt เปิดตัวไปเมื่อปีที่แล้ว ตอนนี้มีการเผยแพร่คำสั่งรูปภาพ Angular (NgOptimizedImage
) เพื่อเปลี่ยนค่าเริ่มต้นของการเพิ่มประสิทธิภาพรูปภาพเป็น Angular
Opportunity
Angular เป็นหนึ่งในเฟรมเวิร์ก JavaScript ชั้นนำที่นักพัฒนาซอฟต์แวร์ใช้ในปัจจุบัน มีการใช้งานโดยต้นทางมากกว่า 5 หมื่นรายการ ซึ่งได้รับการ Crawl โดย HTTPArchive บนอุปกรณ์เคลื่อนที่และมียอดดาวน์โหลดต่อสัปดาห์บน NPM เกือบ 3 ล้านครั้ง
เมื่อพิจารณาคะแนน Core Web Vitals เปอร์เซ็นต์ของต้นทางของ Angular ที่ตรงตามเกณฑ์ LCP ในระดับ "ดี" ยังคงต้องได้รับการแก้ไข มีเว็บไซต์ Angular เพียง 18.74% ที่มี LCP ที่ดีบนอุปกรณ์เคลื่อนที่ในเดือนมิถุนายน 2022 เนื่องจากรูปภาพเป็นองค์ประกอบ LCP ของหน้าเว็บมากกว่า 70% บนอุปกรณ์เคลื่อนที่และเดสก์ท็อป รูปภาพ LCP ที่ไม่ได้เพิ่มประสิทธิภาพจึงอาจเป็นหนึ่งในสาเหตุหลักของ LCP ที่ไม่ดีในเว็บไซต์ของ Angular
คำสั่งรูปภาพ Angular ออกแบบมาเพื่อช่วยปรับปรุงตัวเลขเหล่านี้
MVP สำหรับคำสั่ง NgOptimizeImage
MVP ของคำสั่งรูปภาพ Angular สร้างขึ้นจากบทเรียนจากคอมโพเนนต์รูปภาพที่ Aurora สร้างขึ้นจนถึงปัจจุบัน ขณะที่ปรับการออกแบบให้เข้ากับประสบการณ์การแสดงผลฝั่งไคลเอ็นต์ของ Angular ปัญหาการเพิ่มประสิทธิภาพรูปภาพมาตรฐานส่วนใหญ่ได้รับการแก้ไขด้วยรายการใดรายการหนึ่งต่อไปนี้
- การระบุค่าเริ่มต้นที่ชัดเจน
- การแสดงข้อผิดพลาดหรือคําเตือนเพื่อให้เป็นไปตามแนวทางปฏิบัติแนะนำ
ไฮไลต์ของการออกแบบมีดังนี้
การโหลดแบบ Lazy Loading อัจฉริยะ
รูปภาพที่ผู้ใช้มองไม่เห็นเมื่อโหลดหน้าเว็บ (เช่น รูปภาพครึ่งหน้าล่างหรือรูปภาพภาพสไลด์ที่ซ่อนอยู่) ควรโหลดแบบ Lazy Loading การโหลดแบบ Lazy Loading ช่วยให้มีทรัพยากรของเบราว์เซอร์เพื่อโหลดข้อความ สื่อ หรือสคริปต์ที่สำคัญอื่นๆ รูปภาพส่วนใหญ่ไม่สำคัญและควรโหลดแบบ Lazy Loading แต่มีเพียง 7.8% ของหน้าเว็บที่ใช้การโหลดแบบ Lazy Loading เนทีฟในปี 2021
คำสั่งรูปภาพ Angular แบบ Lazy จะโหลดรูปภาพที่ไม่สำคัญโดยค่าเริ่มต้น และโหลดเฉพาะรูปภาพที่ทําเครื่องหมายว่า
priority
อย่างตั้งใจเท่านั้น วิธีนี้ช่วยให้มั่นใจว่ารูปภาพส่วนใหญ่แสดงพฤติกรรมการโหลดที่เหมาะสมที่สุดการจัดลำดับความสำคัญของรูปภาพที่สำคัญ
การเพิ่มคำแนะนำเกี่ยวกับแหล่งข้อมูล (เช่น
preload
หรือpreconnect
) เพื่อจัดลำดับความสำคัญในการโหลดรูปภาพที่สำคัญเป็นแนวทางปฏิบัติแนะนำ แต่แอปส่วนใหญ่ไม่ได้ใช้งาน จากข้อมูลของ Web Almanac ปี 2021 มีเพียงหน้าสำหรับอุปกรณ์เคลื่อนที่ 12.7% ที่ใช้คำแนะนำในการเชื่อมต่อล่วงหน้าและหน้าในอุปกรณ์เคลื่อนที่เพียง 22.1% ที่ใช้คำแนะนำการโหลดล่วงหน้าคำสั่งเกี่ยวกับรูปภาพจะทำหน้าที่ใน 2 ด้านหน้าเมื่อมีการทำเครื่องหมายว่ารูปภาพเป็นรูปภาพสำคัญ
- โดยตั้งค่าลำดับความสำคัญของการดึงข้อมูลของรูปภาพเป็น
"high"
เพื่อให้เบราว์เซอร์ทราบว่าควรดาวน์โหลดรูปภาพที่มีลำดับความสำคัญสูง - ในโหมดการพัฒนา การตรวจสอบรันไทม์จะยืนยันว่ามีการรวมคำแนะนำด้านทรัพยากร
preconnect
ที่สอดคล้องกับที่มาของรูปภาพ
ในโหมดการพัฒนา คำสั่งจะใช้ PerformanceObserver API เพื่อยืนยันว่าอิมเมจ LCP ได้ทำเครื่องหมายเป็น
priority
ตามที่คาดไว้ หากไม่ได้ทำเครื่องหมายเป็นpriority
ระบบจะแสดงข้อผิดพลาดในคำสั่งให้นักพัฒนาซอฟต์แวร์เพิ่มแอตทริบิวต์priority
ลงในรูปภาพ LCPท้ายที่สุดแล้ว การทำงานอัตโนมัติและความสอดคล้องร่วมกันนี้ช่วยให้มั่นใจว่ารูปภาพ LCP มีคําแนะนํา
preconnect
, ค่าแอตทริบิวต์fetchpriority
เป็นhigh
และไม่ได้โหลดแบบ Lazy Loading- โดยตั้งค่าลำดับความสำคัญของการดึงข้อมูลของรูปภาพเป็น
การกำหนดค่าที่เพิ่มประสิทธิภาพสำหรับเครื่องมือรูปภาพยอดนิยม
ขอแนะนำให้แอปพลิเคชัน Angular ใช้ CDN รูปภาพ ซึ่งมักให้บริการเพิ่มประสิทธิภาพโดยค่าเริ่มต้น
คำสั่งนี้สนับสนุนให้ใช้ CDN รูปภาพโดยการมอบประสบการณ์การใช้งานที่น่าสนใจเป็นพิเศษสำหรับนักพัฒนาซอฟต์แวร์ (DX) ในการกำหนดค่าในแอป โดยรองรับ API ตัวโหลดที่ช่วยให้คุณกำหนดผู้ให้บริการ CDN และ URL ฐานในการกำหนดค่าได้ เมื่อกําหนดค่าแล้ว คุณต้องกําหนดชื่อเนื้อหาในมาร์กอัปเท่านั้น ตัวอย่างเช่น
// in module providers: provideImgixLoader('https://mysite.net/assets/') // in markup <img ngSrc="image.png" > <img ngSrc="image2.png" >
ซึ่งเทียบเท่ากับการรวมแท็กรูปภาพต่อไปนี้และลดมาร์กอัปมาร์กอัปที่นักพัฒนาต้องระบุสำหรับรูปภาพทุกรูป
<img src="https://mysite.net/assets/image.png"> <img src="https://mysite.net/assets/image2.png">
คำสั่งรูปภาพช่วยให้ตัวโหลดในตัวมีการกำหนดค่าที่เหมาะสมที่สุดสำหรับ CDN รูปภาพยอดนิยม ตัวโหลดเหล่านี้จะจัดรูปแบบ URL รูปภาพโดยอัตโนมัติเพื่อให้แน่ใจว่าใช้รูปแบบรูปภาพที่แนะนำและการตั้งค่าการบีบอัดสำหรับแต่ละ CDN
ข้อผิดพลาดและคำเตือนในตัว
นอกเหนือจากการเพิ่มประสิทธิภาพในตัวข้างต้นแล้ว คำสั่งนี้ยังมีการตรวจสอบในตัวเพื่อให้มั่นใจว่านักพัฒนาแอปได้ทำตามแนวทางปฏิบัติแนะนำที่แนะนำในมาร์กอัปรูปภาพ คำสั่งรูปภาพจะตรวจสอบต่อไปนี้
รูปภาพที่ไม่ได้ปรับขนาด: คำสั่งรูปภาพจะแสดงข้อผิดพลาดหากมาร์กอัปรูปภาพไม่ได้กำหนดความกว้างและความสูงไว้อย่างชัดเจน รูปภาพที่ไม่ได้ปรับขนาดอาจทำให้เกิดการเปลี่ยนแปลงเลย์เอาต์ ซึ่งส่งผลต่อเมตริก Cumulative Layout Shift (CLS) ของหน้าเว็บ แนวทางปฏิบัติแนะนำเพื่อป้องกันปัญหานี้คือรูปภาพควรมีการระบุแอตทริบิวต์
width
และheight
สัดส่วนภาพ: คำสั่งรูปภาพจะแสดงข้อผิดพลาดเพื่อแจ้งให้นักพัฒนาซอฟต์แวร์ทราบว่าสัดส่วนภาพ
width
:height
ที่กำหนดไว้ใน HTML ไม่ได้ใกล้เคียงกับสัดส่วนภาพจริงของรูปภาพที่แสดงหรือไม่ ซึ่งอาจทำให้รูปภาพดูบิดเบี้ยวบนหน้าจอ กรณีนี้อาจเกิดขึ้นได้หาก- คุณได้กำหนดขนาดที่ไม่ถูกต้อง (ความกว้างหรือความสูง) โดยไม่ได้ตั้งใจ หรือ
- หากคุณกำหนดขนาดหนึ่งตามเปอร์เซ็นต์ใน CSS แต่ไม่ได้กำหนดอีกขนาดหนึ่ง (เช่น
width: 100%
ต้องใช้height: auto
เพื่อให้รูปภาพเพิ่มขึ้นในทั้ง 2 ขนาด)
รูปภาพที่เกินขนาด: หากรูปภาพไม่ได้ระบุ
srcset
และรูปภาพภายในมีขนาดใหญ่กว่ารูปภาพที่แสดงผลอย่างมาก คำสั่งจะแสดงคำเตือนที่แนะนำให้ใช้แอตทริบิวต์srcset
และsizes
ความหนาแน่นของรูปภาพ: คำสั่งจะแสดงข้อผิดพลาดหากคุณพยายามรวมรูปภาพใน
srcset
ที่มีความหนาแน่นของพิกเซลมากกว่า3x
เราไม่แนะนำให้ใช้ข้อบ่งชี้ที่สูงกว่า2x
เนื่องจากมีผลให้อุปกรณ์เคลื่อนที่ที่มีความละเอียดสูงต้องดาวน์โหลดรูปภาพขนาดใหญ่โดยไม่เจตนา นอกจากนี้ สายตามนุษย์ก็ไม่สามารถบอกความแตกต่างได้มากกว่า 2 เท่า
ชาเลนจ์
การปรับกลยุทธ์การเพิ่มประสิทธิภาพรูปภาพเพื่อให้ทำงานในเฟรมเวิร์กฝั่งไคลเอ็นต์เป็นความท้าทายหลักในการออกแบบ NgOptimizedImage
ประสบการณ์การแสดงผลเริ่มต้นใน Next.js คือการแสดงผลฝั่งเซิร์ฟเวอร์ (SSR) หรือการสร้างไซต์แบบคงที่ (SSG) ขณะที่ใน Angular คือการแสดงผลฝั่งไคลเอ็นต์ (CSR) แม้ว่า Angular จะรองรับไลบรารี SSR แบบ angular/Universal แอป Angular ส่วนใหญ่ (ประมาณ 60%) ใช้ CSR
คำสั่งรูปภาพสร้างขึ้นเพื่อ CSR ทั้งหมดเพื่อให้สอดคล้องกับกรณีการใช้งานทั่วไปในแอป Angular จึงเป็นการสร้างข้อจำกัดเพิ่มเติม ทำให้ทีมงานต้องคิดใหม่หาวิธีเพิ่มประสิทธิภาพให้แอป CSR โดยเฉพาะ
ปัญหาบางส่วนที่พบมีดังนี้
คําแนะนําเกี่ยวกับแหล่งข้อมูลสนับสนุน
การโหลดเนื้อหาสำคัญล่วงหน้าจะช่วยให้เบราว์เซอร์ค้นพบเนื้อหาเหล่านั้นได้เร็วขึ้น อย่างไรก็ตาม การรวมคำแนะนำด้านทรัพยากรในแอป Angular จะซับซ้อนเนื่องจาก
การเพิ่มด้วยตนเอง: นักพัฒนาแอปจะเพิ่มคำแนะนำเกี่ยวกับทรัพยากร
preload
ด้วยตนเองได้ยาก Angular ใช้ไฟล์ index.html ที่แชร์ร่วมกัน 1 ไฟล์สําหรับทั้งโปรเจ็กต์หรือทุกเส้นทางในเว็บไซต์ ดังนั้น<head>
ของเอกสารจึงจะเหมือนกันในทุกเส้นทาง (อย่างน้อยเวลาที่แสดง) การเพิ่มคำแนะนำpreload
ใน<head>
จะทำให้ทรัพยากรจะถูกโหลดล่วงหน้าสำหรับทุกเส้นทางแม้ในกรณีที่ไม่จำเป็นต้องใช้ จึงไม่แนะนําให้เพิ่มคําแนะนําpreload
รายการด้วยตนเองการเพิ่มอัตโนมัติระหว่างการแสดงผล: การใช้เฟรมเวิร์กเพื่อเพิ่มคำแนะนำการโหลดล่วงหน้าที่ส่วนหัวของเอกสารระหว่างการแสดงผลในแอป CSR จะไม่ช่วยแก้ปัญหา เนื่องจากการแสดงผลจะเกิดขึ้นหลังจากที่ดาวน์โหลดและเรียกใช้ JavaScript แล้ว
<head>
จะแสดงผลช้าเกินกว่าที่จะใช้ค่าใดๆ ได้สำหรับคำสั่งเวอร์ชันแรก ชุดค่าผสมของคำแนะนำ
preconnect
และfetchpriority
จะแสดงเพื่อจัดลำดับความสำคัญของรูปภาพแทนpreload
อย่างไรก็ตาม ตอนนี้ Aurora กำลังทำงานร่วมกับทีม Angular CLI เพื่อเปิดใช้การแทรกคำแนะนำทรัพยากรโดยอัตโนมัติในเวลาบิลด์ โปรดอดใจรอการเพิ่มประสิทธิภาพขนาดและรูปแบบรูปภาพในเซิร์ฟเวอร์
เนื่องจากแอป Angular มักจะแสดงผลฝั่งไคลเอ็นต์ ระบบไฟล์จึงไม่สามารถบีบอัดรูปภาพได้ในเวลาที่ขอและแสดงผลตามที่เป็นอยู่ ด้วยเหตุนี้ เราจึงแนะนำให้ใช้ CDN รูปภาพเพื่อบีบอัดรูปภาพและแปลงเป็นรูปแบบใหม่ๆ เช่น WebP หรือ AVIF ตามคำขอ
แม้ว่าคำสั่งดังกล่าวจะไม่ได้บังคับใช้การใช้ CDN รูปภาพ แต่ขอแนะนำให้ใช้ CDN กับคำสั่งและตัวโหลดในตัวเพื่อให้แน่ใจว่ามีการใช้ตัวเลือกการกำหนดค่าที่ถูกต้อง
มีอิทธิพล
การสาธิตต่อไปนี้จะแสดงให้เห็นความแตกต่างของคำสั่งรูปภาพ Angular ที่มีต่อประสิทธิภาพของรูปภาพ โดยจะเปรียบเทียบเว็บไซต์ 2 แห่งต่อไปนี้
เว็บไซต์ 1: ใช้องค์ประกอบ <img>
แบบเนทีฟกับรูปภาพที่แสดงผ่าน Imgix CDN (โดยมีตัวเลือกการกำหนดค่าเริ่มต้น)
เว็บไซต์ 2: ใช้คำสั่งรูปภาพสำหรับรูปภาพทั้งหมด นอกจากนี้ยังรวมถึงการเพิ่มประสิทธิภาพที่คำสั่งดังกล่าวแนะนำโดยตรงหรือข้อผิดพลาดด้วย
ทีมทำงานร่วมกับพาร์ทเนอร์เพื่อตรวจสอบผลกระทบด้านประสิทธิภาพของคำสั่งรูปภาพที่มีต่อแอปพลิเคชัน Angular ขององค์กรจริง
หนึ่งในพาร์ทเนอร์เหล่านี้คือ Land's End เราคาดว่าเว็บไซต์ของบริษัทจะเป็นตัวอย่างที่ดีสำหรับผลลัพธ์ที่แอปพลิเคชันจริงอาจเห็น
มีการทดสอบในห้องปฏิบัติการของ Lighthouse ในสภาพแวดล้อม QA ก่อนและหลังการใช้คำสั่งรูปภาพ บนเดสก์ท็อป ค่ามัธยฐานของ LCP ลดลงจาก 12.0 เป็น 3.0 วินาที ซึ่ง LCP เพิ่มขึ้น 75% บนอุปกรณ์เคลื่อนที่ ค่ามัธยฐานของ LCP ลดลงจาก 20.2 เป็น 12.0 วินาที (ปรับปรุงขึ้น 40.6%)
แผนกลยุทธ์ในอนาคต
นี่เป็นเพียงส่วนแรกของการออกแบบคำสั่งรูปภาพ Angular ยังมีฟีเจอร์อื่นๆ อีกมากมายที่วางแผนไว้สำหรับเวอร์ชันในอนาคต ได้แก่
การรองรับรูปภาพที่ตอบสนองตามอุปกรณ์ที่ดีขึ้น
ปัจจุบัน
NgOptimizedImage
รองรับการใช้srcset
แล้ว แต่คุณต้องระบุแอตทริบิวต์srcset
และsizes
สำหรับแต่ละรูปภาพด้วยตนเอง ในอนาคต คำสั่งนี้อาจสร้างแอตทริบิวต์srcset
และsizes
โดยอัตโนมัติการแทรกคำแนะนำทรัพยากรโดยอัตโนมัติ
คุณอาจผสานรวมกับ Angular CLI เพื่อสร้างแท็กการเชื่อมต่อล่วงหน้าและโหลดล่วงหน้าสำหรับรูปภาพ LCP ที่สำคัญได้
การรองรับ Angular SSR
เวอร์ชัน MVP ออกแบบมาให้คำนึงถึงข้อจำกัดของ Angular CSR แต่การสำรวจโซลูชันการเพิ่มประสิทธิภาพรูปภาพสำหรับ Angular SSR (เชิงมุม/สากล) ก็มีความสำคัญเช่นกัน
การปรับปรุงประสบการณ์ของนักพัฒนาแอป
NgOptimizedImage
กำหนดให้ระบุแอตทริบิวต์width
และheight
สำหรับแต่ละรูปภาพ อย่างไรก็ตาม การระบุตัวเลือกเหล่านี้ให้กับแต่ละอิมเมจอาจเป็นเรื่องที่น่าเบื่อหน่ายสำหรับนักพัฒนาซอฟต์แวร์บางราย มีโอกาสในการปรับปรุงประสบการณ์ของนักพัฒนาซอฟต์แวร์ในครั้งต่อๆ ไปดังนี้- รองรับโหมดเพิ่มเติม (คล้ายกับตัวเลือกเลย์เอาต์รูปภาพใน Next.js "
fill
") ที่ไม่ต้องกำหนดความกว้าง/ความสูงอย่างชัดแจ้ง - การใช้การผสานรวม CLI เพื่อตั้งค่าความกว้างและความสูงโดยอัตโนมัติสำหรับรูปภาพในเครื่องโดยการกำหนดขนาดจริงของรูปภาพ
- รองรับโหมดเพิ่มเติม (คล้ายกับตัวเลือกเลย์เอาต์รูปภาพใน Next.js "
บทสรุป
คำสั่งรูปภาพ Angular จะพร้อมใช้งานสำหรับนักพัฒนาแอปในหลายขั้นตอน เริ่มตั้งแต่เวอร์ชันตัวอย่างสำหรับนักพัฒนาซอฟต์แวร์ในเวอร์ชัน v14.2.0 ลองใช้ NgOptimizedImage
แล้วแสดงความคิดเห็นเลย
ขอขอบคุณเป็นพิเศษสำหรับ Katie Hempenius และ Alex Castle สำหรับการมีส่วนร่วม