การสร้างคอมโพเนนต์รูปภาพที่มีประสิทธิภาพ

คอมโพเนนต์รูปภาพสรุปแนวทางปฏิบัติแนะนำเกี่ยวกับประสิทธิภาพ และให้โซลูชันที่พร้อมใช้งานทันทีเพื่อเพิ่มประสิทธิภาพรูปภาพ

Leena Sohoni
Leena Sohoni
Kara Erickson
Kara Erickson
Alex Castle
Alex Castle

รูปภาพเป็นสาเหตุที่พบบ่อยของการเกิดจุดคอขวดด้านประสิทธิภาพสำหรับเว็บแอปพลิเคชัน และเป็นส่วนที่มุ่งเน้นสำคัญในการเพิ่มประสิทธิภาพ รูปภาพที่ไม่ได้เพิ่มประสิทธิภาพจะมีส่วนทำให้เกิดการขยายหน้าเว็บ และมีสัดส่วนมากกว่า 70% ของน้ำหนักหน้าเว็บโดยรวมเป็นไบต์ที่เปอร์เซ็นไทล์ที่ 90 วิธีต่างๆ ในการเพิ่มประสิทธิภาพรูปภาพเรียก "คอมโพเนนต์รูปภาพ" อัจฉริยะ พร้อมโซลูชันประสิทธิภาพต่างๆ รวมอยู่เป็นค่าเริ่มต้น

ทีม Aurora ทำงานร่วมกับ Next.js เพื่อสร้างคอมโพเนนต์ดังกล่าวเพียงอันเดียว โดยมีเป้าหมายเพื่อสร้างเทมเพลตรูปภาพที่มีการเพิ่มประสิทธิภาพ ซึ่งนักพัฒนาเว็บจะปรับแต่งเพิ่มเติมได้ คอมโพเนนต์นี้ทำหน้าที่เป็นต้นแบบที่ดีและเป็นมาตรฐานในการสร้างคอมโพเนนต์รูปภาพในเฟรมเวิร์กอื่นๆ ระบบจัดการเนื้อหา (CMS) และสแต็กเทคโนโลยี เราได้ร่วมงานกับคอมโพเนนต์สำหรับ Nuxt.js ที่คล้ายกัน และเรากำลังทำงานร่วมกับ Angular ในการเพิ่มประสิทธิภาพรูปภาพในเวอร์ชันต่อๆ ไป โพสต์นี้กล่าวถึงวิธีที่เราออกแบบคอมโพเนนต์รูปภาพ Next.js และบทเรียนที่เราได้เรียนรู้ไปตลอด

คอมโพเนนต์รูปภาพที่เป็นส่วนขยายของรูปภาพ

ปัญหาและโอกาสในการเพิ่มประสิทธิภาพรูปภาพ

รูปภาพไม่เพียงส่งผลต่อประสิทธิภาพเท่านั้น แต่ยังส่งผลต่อธุรกิจด้วย จำนวนรูปภาพในหน้าเว็บเป็นตัวคาดการณ์ Conversion ที่สำคัญอันดับ 2 ของผู้ใช้ที่เข้าชมเว็บไซต์ เซสชันที่ผู้ใช้ทำ Conversion มีรูปภาพน้อยกว่าเซสชันที่ไม่ได้ทำ Conversion ถึง 38% Lighthouse แสดงโอกาสมากมายในการเพิ่มประสิทธิภาพรูปภาพและปรับปรุง Web Vitals ซึ่งเป็นส่วนหนึ่งของการตรวจสอบแนวทางปฏิบัติแนะนำ พื้นที่ส่วนกลางที่รูปภาพอาจส่งผลต่อ Core Web Vitals และประสบการณ์ของผู้ใช้มีดังนี้

รูปภาพที่ไม่ปรับขนาดทำให้ CLS เสียหาย

รูปภาพที่แสดงโดยไม่ได้ระบุขนาดไว้อาจทำให้เลย์เอาต์ไม่เสถียรและส่งผลให้เกิด Cumulative Layout Shift (CLS) ในระดับสูง การตั้งค่าแอตทริบิวต์ width และ height ในองค์ประกอบ img จะช่วยป้องกันการเปลี่ยนเลย์เอาต์ได้ เช่น

<img src="flower.jpg" width="360" height="240">

ควรตั้งค่าความกว้างและความสูงให้สัดส่วนภาพที่แสดงผลใกล้เคียงกับสัดส่วนภาพธรรมชาติ สัดส่วนภาพที่ต่างกันอย่างมากอาจส่งผลให้รูปภาพบิดเบี้ยว พร็อพเพอร์ตี้ที่ค่อนข้างใหม่ซึ่งให้คุณระบุอัตราส่วนใน CSS จะช่วยปรับขนาดรูปภาพให้ปรับเปลี่ยนตามอุปกรณ์ในขณะที่ป้องกัน CLS ได้

รูปภาพขนาดใหญ่อาจส่งผลเสียต่อ LCP

ยิ่งไฟล์รูปภาพมีขนาดใหญ่เท่าใด การดาวน์โหลดก็จะยิ่งนานขึ้นเท่านั้น รูปภาพขนาดใหญ่อาจเป็น "รูปภาพหลัก" รูปภาพสำหรับหน้าเว็บหรือองค์ประกอบที่สำคัญที่สุดในวิวพอร์ตซึ่งทำหน้าที่ทริกเกอร์ Largest Contentful Paint (LCP) รูปภาพที่เป็นส่วนหนึ่งของเนื้อหาสำคัญและใช้เวลาดาวน์โหลดนานจะทำให้ LCP ทำงานล่าช้า

ในหลายกรณี นักพัฒนาซอฟต์แวร์สามารถลดขนาดรูปภาพผ่านการบีบอัดที่ดีขึ้นและการใช้รูปภาพที่ปรับเปลี่ยนตามอุปกรณ์ แอตทริบิวต์ srcset และ sizes ขององค์ประกอบ <img> ช่วยให้ระบุไฟล์ภาพที่มีขนาดแตกต่างกันได้ จากนั้นเบราว์เซอร์จะเลือกหน้าจอที่เหมาะสมได้ตามขนาดและความละเอียดของหน้าจอ

การบีบอัดรูปภาพที่ไม่ดีอาจส่งผลเสียต่อ LCP

รูปแบบรูปภาพที่ทันสมัยอย่าง AVIF หรือ WebP สามารถบีบอัดได้ดีกว่ารูปแบบ JPEG และ PNG ที่ใช้กันทั่วไป การบีบอัดที่ดีขึ้นจะลดขนาดไฟล์ลง 25% ถึง 50% ในบางกรณีเพื่อให้รูปภาพมีคุณภาพเท่ากัน ซึ่งการลดนี้จะช่วยให้ดาวน์โหลดได้เร็วขึ้นและใช้อินเทอร์เน็ตน้อยลง แอปควรแสดงรูปแบบรูปภาพที่ทันสมัยในเบราว์เซอร์ที่รองรับรูปแบบเหล่านี้

การโหลดรูปภาพที่ไม่จำเป็นจะทำให้ LCP เสีย

รูปภาพที่อยู่ครึ่งหน้าล่างหรือไม่อยู่ในวิวพอร์ตจะไม่แสดงให้ผู้ใช้เห็นเมื่อหน้าเว็บโหลดขึ้น เลื่อนออกไปได้เพื่อไม่ให้มีนำไปสนับสนุน LCP และเลื่อนเวลาออกไปได้ การโหลดแบบ Lazy Loading สามารถใช้เพื่อโหลดรูปภาพดังกล่าวในภายหลังขณะที่ผู้ใช้เลื่อนดูภาพ

ความท้าทายในการเพิ่มประสิทธิภาพ

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

  • ลำดับความสำคัญ: นักพัฒนาเว็บมักจะให้ความสำคัญกับโค้ด, JavaScript และการเพิ่มประสิทธิภาพข้อมูล ด้วยเหตุนี้ บุคคลเหล่านี้อาจไม่ทราบถึงปัญหาเกี่ยวกับรูปภาพหรือวิธีเพิ่มประสิทธิภาพ รูปภาพที่สร้างโดยนักออกแบบหรือที่ผู้ใช้อัปโหลดอาจไม่มีอยู่ในรายการลำดับความสำคัญสูง
  • โซลูชันที่พร้อมใช้งานทันที: แม้นักพัฒนาซอฟต์แวร์จะตระหนักถึงความแตกต่างเล็กๆ น้อยๆ ของการเพิ่มประสิทธิภาพให้รูปภาพ แต่การไม่มีโซลูชันแบบครบวงจรสำหรับเฟรมเวิร์กหรือเทคโนโลยีพื้นฐานอาจเป็นอุปสรรค
  • รูปภาพแบบไดนามิก: นอกจากภาพนิ่งที่เป็นส่วนหนึ่งของแอปพลิเคชันแล้ว รูปภาพแบบไดนามิกยังอัปโหลดโดยผู้ใช้หรือมาจากฐานข้อมูลภายนอกหรือ CMS การกำหนดขนาดของรูปภาพดังกล่าวโดยที่แหล่งที่มาของรูปภาพเป็นแบบไดนามิกนั้นอาจทำได้ยาก
  • มีมาร์กอัปมากเกินไป: โซลูชันการรวมขนาดรูปภาพหรือ srcset สำหรับขนาดต่างๆ ต้องมีมาร์กอัปเพิ่มเติมสำหรับรูปภาพทุกรูป ซึ่งอาจน่าเบื่อ แอตทริบิวต์ srcset เปิดตัวในปี 2014 แต่ปัจจุบันใช้โดยเว็บไซต์เพียง 26.5% ในปัจจุบัน เมื่อใช้ srcset นักพัฒนาแอปจะต้องสร้างรูปภาพเป็นขนาดต่างๆ เครื่องมืออย่าง just-gimme-an-img ช่วยได้ แต่ต้องใช้ด้วยตนเองสำหรับทุกๆ รูปภาพ
  • การรองรับเบราว์เซอร์: รูปแบบรูปภาพสมัยใหม่ เช่น AVIF และ WebP จะสร้างไฟล์ภาพที่มีขนาดเล็กลง แต่ต้องมีการจัดการเป็นพิเศษในเบราว์เซอร์ที่ไม่รองรับไฟล์ดังกล่าว นักพัฒนาซอฟต์แวร์ต้องใช้กลยุทธ์ เช่น การเจรจาต่อรองเนื้อหาหรือองค์ประกอบ <picture> เพื่อให้แสดงรูปภาพไปยังทุกเบราว์เซอร์
  • ข้อมูลแทรกเกี่ยวกับการโหลดแบบ Lazy Loading: มีเทคนิคและไลบรารีมากมายที่พร้อมสำหรับการใช้งานการโหลดแบบ Lazy Loading สำหรับรูปภาพครึ่งหน้าล่าง การเลือกรายการที่ดีที่สุดอาจเป็นเรื่องท้าทาย นอกจากนี้ นักพัฒนาแอปอาจไม่ทราบระยะที่ดีที่สุดจาก "การพับ" เพื่อโหลดภาพที่เลื่อน ขนาดวิวพอร์ตที่แตกต่างกันบนอุปกรณ์อาจทำให้ปัญหานี้ซับซ้อนยิ่งขึ้น
  • การเปลี่ยนแปลงภูมิทัศน์: เมื่อเบราว์เซอร์เริ่มรองรับฟีเจอร์ HTML หรือ CSS ใหม่ๆ เพื่อเพิ่มประสิทธิภาพ อาจทำให้นักพัฒนาซอฟต์แวร์ประเมินแต่ละฟีเจอร์ได้ยาก เช่น Chrome จะเปิดตัวฟีเจอร์ดึงข้อมูลลำดับความสำคัญเป็นช่วงทดลองใช้จากต้นทาง โดยจะใช้เพื่อเพิ่มลำดับความสำคัญของรูปภาพที่เจาะจงในหน้าเว็บได้ โดยรวมแล้ว นักพัฒนาแอปจะใช้งานง่ายขึ้นหากมีการประเมินการเพิ่มประสิทธิภาพดังกล่าวและนำไปใช้ในระดับคอมโพเนนต์

คอมโพเนนต์รูปภาพเป็นโซลูชัน

โอกาสในการเพิ่มประสิทธิภาพรูปภาพที่มีอยู่ รวมถึงความท้าทายในการนำรูปภาพแต่ละรูปไปใช้กับทุกแอปพลิเคชันนั้นทำให้เราเกิดแนวคิดเกี่ยวกับคอมโพเนนต์รูปภาพ คอมโพเนนต์รูปภาพสามารถสรุปและบังคับใช้แนวทางปฏิบัติแนะนำได้ การแทนที่องค์ประกอบ <img> ด้วยคอมโพเนนต์รูปภาพจะช่วยให้นักพัฒนาแอปแก้ไขปัญหาด้านประสิทธิภาพของรูปภาพได้ดีขึ้น

ในช่วงปีที่ผ่านมา เราได้ใช้เฟรมเวิร์ก Next.js เพื่อออกแบบและใช้งานคอมโพเนนต์รูปภาพ โดยสามารถใช้แทนค่าเดิมในการแทนที่องค์ประกอบ <img> ที่มีอยู่ในแอป Next.js ได้ดังนี้

// Before with <img> element:
function Logo() {
  return <img src="/logo.jpg" alt="logo" height="200" width="100" />
}

// After with image component:
import Image from 'next/image'

function Logo() {
  return <Image src="/logo.jpg" alt="logo" height="200" width="100" />
}

คอมโพเนนต์จะพยายามระบุปัญหาเกี่ยวกับรูปภาพโดยทั่วไปผ่านชุดฟีเจอร์และหลักการที่หลากหลาย นอกจากนี้ยังมีตัวเลือกที่อนุญาตให้นักพัฒนาแอปปรับแต่งรูปภาพให้เหมาะกับข้อกำหนดต่างๆ เกี่ยวกับรูปภาพด้วย

การป้องกันการเปลี่ยนแปลงเลย์เอาต์

ตามที่กล่าวไปก่อนหน้านี้ รูปภาพที่ไม่ปรับขนาดทำให้เลย์เอาต์เกิดการเปลี่ยนแปลงและส่งผลต่อ CLS เมื่อใช้คอมโพเนนต์รูปภาพ Next.js นักพัฒนาซอฟต์แวร์ต้องระบุขนาดรูปภาพโดยใช้แอตทริบิวต์ width และ height เพื่อป้องกันไม่ให้เลย์เอาต์เปลี่ยนแปลง หากไม่ทราบขนาด นักพัฒนาแอปต้องระบุ layout=fill เพื่อแสดงรูปภาพที่ไม่ได้ปรับขนาดภายในคอนเทนเนอร์ที่มีขนาดดังกล่าว หรือคุณสามารถใช้การนำเข้าภาพนิ่งเพื่อดึงขนาดของภาพจริงบนฮาร์ดไดรฟ์ที่เวลาบิลด์ แล้วรวมไว้ในภาพนั้น

// Image component with width and height specified
<Image src="/logo.jpg" alt="logo" height="200" width="100" />

// Image component with layout specified
<Image src="/hero.jpg" layout="fill" objectFit="cover" alt="hero" />

// Image component with image import
import Image from 'next/image'
import logo from './logo.png'

function Logo() {
  return <Image src={logo} alt="logo" />
}

เนื่องจากนักพัฒนาซอฟต์แวร์ไม่สามารถใช้คอมโพเนนต์รูปภาพที่ไม่ได้ปรับขนาดได้ การออกแบบนี้จึงช่วยให้พวกเขาใช้เวลาในการพิจารณาการปรับขนาดรูปภาพและป้องกันไม่ให้เลย์เอาต์เปลี่ยนแปลง

อำนวยความสะดวกด้านการตอบสนอง

หากต้องการทำให้รูปภาพปรับเปลี่ยนตามอุปกรณ์ นักพัฒนาแอปต้องตั้งค่าแอตทริบิวต์ srcset และ sizes ในองค์ประกอบ <img> เราจึงต้องการลดความพยายามนี้กับคอมโพเนนต์รูปภาพ เราออกแบบคอมโพเนนต์รูปภาพ Next.js เพื่อตั้งค่าแอตทริบิวต์เพียงครั้งเดียวต่อแอปพลิเคชัน โดยเราจะนำพารามิเตอร์เหล่านี้ไปใช้กับอินสแตนซ์ทั้งหมดของคอมโพเนนต์รูปภาพตามโหมดเลย์เอาต์ เราจึงได้คิดโซลูชันที่มี 3 ส่วน ดังนี้

  1. พร็อพเพอร์ตี้ deviceSizes: พร็อพเพอร์ตี้นี้ใช้เพื่อกำหนดค่าเบรกพอยท์แบบครั้งเดียวตามอุปกรณ์ที่ใช้งานกับฐานผู้ใช้ของแอปพลิเคชันได้ ค่าเริ่มต้นของเบรกพอยท์จะรวมอยู่ในไฟล์การกำหนดค่า
  2. พร็อพเพอร์ตี้ imageSizes: ยังเป็นพร็อพเพอร์ตี้ที่กำหนดค่าได้ซึ่งใช้เพื่อรับขนาดรูปภาพที่สอดคล้องกับเบรกพอยท์ของขนาดอุปกรณ์
  3. แอตทริบิวต์ layout ในแต่ละรูปภาพ: ใช้เพื่อระบุวิธีใช้คุณสมบัติ deviceSizes และ imageSizes สำหรับแต่ละรูปภาพ ค่าที่รองรับสำหรับโหมดเลย์เอาต์คือ fixed, fill, intrinsic และ responsive

เมื่อมีการขอรูปภาพด้วยโหมดเลย์เอาต์แบบปรับเปลี่ยนตามอุปกรณ์หรือ fill Next.js จะระบุรูปภาพที่จะแสดงโดยอิงตามขนาดของอุปกรณ์ที่ขอหน้าเว็บและตั้งค่า srcset และ sizes ในรูปภาพอย่างเหมาะสม

การเปรียบเทียบต่อไปนี้แสดงวิธีใช้โหมดเลย์เอาต์เพื่อควบคุมขนาดของรูปภาพในหน้าจอต่างๆ เราได้ใช้รูปภาพสาธิตที่แชร์ในเอกสาร Next.js ซึ่งดูบนโทรศัพท์และแล็ปท็อปมาตรฐาน

หน้าจอแล็ปท็อป หน้าจอโทรศัพท์
เลย์เอาต์ = ภายใน: ปรับขนาดลงให้พอดีกับความกว้างของคอนเทนเนอร์บนวิวพอร์ตขนาดเล็ก ไม่ปรับขนาดเกินขนาดที่แท้จริงของรูปภาพในวิวพอร์ตที่ใหญ่กว่า ความกว้างของคอนเทนเนอร์อยู่ที่ 100%
รูปภาพภูเขาแสดงตามที่เห็น รูปภาพภูเขาลดขนาดลงแล้ว
เลย์เอาต์ = แก้ไขแล้ว: รูปภาพไม่ตอบสนอง ความกว้างและความสูงคงที่คล้ายกับองค์ประกอบ "" โดยไม่คำนึงถึงอุปกรณ์ที่แสดงผล
รูปภาพภูเขาแสดงตามที่เห็น รูปภาพภูเขาที่แสดงไม่พอดีกับหน้าจอ
เลย์เอาต์ = ปรับเปลี่ยนตามอุปกรณ์: ลดขนาดหรือปรับขนาดตามความกว้างของคอนเทนเนอร์ในวิวพอร์ตที่แตกต่างกัน โดยคงสัดส่วนภาพไว้
รูปภาพภูเขาปรับขนาดให้พอดีกับหน้าจอ รูปภาพภูเขาลดขนาดลงให้พอดีกับหน้าจอ
เลย์เอาต์ = เติม: ความกว้างและความสูงที่ยืดออกไปเพื่อให้พอดีกับคอนเทนเนอร์หลัก (ในตัวอย่างนี้กำหนดความกว้างของ <div> ระดับบนสุดเป็น 300*500)
แสดงรูปภาพภูเขาให้พอดีกับขนาด 300*500 แสดงรูปภาพภูเขาให้พอดีกับขนาด 300*500
รูปภาพที่แสดงผลสำหรับเลย์เอาต์แบบต่างๆ

มอบการโหลดแบบ Lazy Loading ในตัว

คอมโพเนนต์รูปภาพมีโซลูชันการโหลดแบบ Lazy Loading ในตัวที่มีประสิทธิภาพเป็นค่าเริ่มต้น เมื่อใช้องค์ประกอบ <img> มีตัวเลือก 2-3 อย่างสำหรับการโหลดแบบ Lazy Loading แต่ก็มีข้อเสียทั้งหมดที่ทำให้ใช้งานยาก นักพัฒนาแอปอาจใช้วิธีใดวิธีหนึ่งต่อไปนี้สำหรับการโหลดแบบ Lazy Loading

  • ระบุแอตทริบิวต์ loading: ตัวเลือกนี้รองรับในเบราว์เซอร์รุ่นใหม่ทั้งหมด
  • ใช้ Intersection Observer API: การสร้างโซลูชันการโหลดแบบ Lazy Loading ที่กําหนดเองต้องใช้ความพยายามและการออกแบบและการติดตั้งใช้งานที่รอบคอบ นักพัฒนาซอฟต์แวร์อาจไม่มีเวลาดำเนินการดังกล่าวเสมอไป
  • นำเข้าไลบรารีของบุคคลที่สามไปยังรูปภาพที่โหลดแบบ Lazy Loading: อาจต้องใช้ความพยายามมากขึ้นในการประเมินและผสานรวมไลบรารีของบุคคลที่สามที่เหมาะสมสำหรับการโหลดแบบ Lazy Loading

ในคอมโพเนนต์รูปภาพ Next.js การโหลดจะตั้งค่าเป็น "lazy" โดยค่าเริ่มต้น การโหลดแบบ Lazy Loading จะใช้งานโดยใช้ Intersection Observer ซึ่งใช้ได้ในเบราว์เซอร์รุ่นใหม่ส่วนใหญ่ นักพัฒนาแอปไม่จำเป็นต้องดำเนินการใดๆ เพิ่มเติมเพื่อเปิดใช้ แต่สามารถปิดใช้ได้เมื่อต้องการ

โหลดรูปภาพที่สำคัญล่วงหน้า

บ่อยครั้งที่องค์ประกอบ LCP คือรูปภาพ และรูปภาพขนาดใหญ่อาจทำให้ LCP ล่าช้าได้ เราขอแนะนำให้คุณโหลดรูปภาพที่สำคัญไว้ล่วงหน้าเพื่อให้เบราว์เซอร์ค้นพบรูปภาพนั้นได้เร็วขึ้น เมื่อใช้องค์ประกอบ <img> คำแนะนำการโหลดล่วงหน้าอาจรวมอยู่ในส่วนหัว HTML ดังนี้

<link rel="preload" as="image" href="important.png">

คอมโพเนนต์รูปภาพที่ออกแบบมาอย่างดีควรนำเสนอวิธีปรับแต่งลำดับการโหลดของรูปภาพ ไม่ว่าจะใช้เฟรมเวิร์กใดก็ตาม ในกรณีของคอมโพเนนต์รูปภาพ Next.js นักพัฒนาซอฟต์แวร์สามารถระบุรูปภาพที่เป็นตัวเลือกที่ดีสำหรับการโหลดล่วงหน้าโดยใช้แอตทริบิวต์ priority ของคอมโพเนนต์รูปภาพ

<Image src="/hero.jpg" alt="hero" height="400" width="200" priority />

การเพิ่มแอตทริบิวต์ priority จะช่วยให้มาร์กอัปง่ายขึ้นและใช้ได้สะดวกยิ่งขึ้น นักพัฒนาคอมโพเนนต์รูปภาพยังสำรวจตัวเลือกในการใช้การเรียนรู้เพื่อกำหนดการโหลดล่วงหน้าโดยอัตโนมัติสำหรับรูปภาพครึ่งหน้าบนในหน้าที่เป็นไปตามเกณฑ์ที่เจาะจงได้ด้วย

ส่งเสริมการโฮสต์รูปภาพประสิทธิภาพสูง

แนะนำให้ใช้ CDN สำหรับรูปภาพสำหรับการเพิ่มประสิทธิภาพรูปภาพโดยอัตโนมัติ และยังรองรับรูปแบบรูปภาพที่ทันสมัย เช่น WebP และ AVIF ด้วย คอมโพเนนต์รูปภาพ Next.js ใช้ CDN รูปภาพโดยค่าเริ่มต้นโดยใช้สถาปัตยกรรมตัวโหลด ตัวอย่างต่อไปนี้แสดงให้เห็นว่าตัวโหลดอนุญาตให้กำหนดค่า CDN ในไฟล์การกำหนดค่า Next.js ได้

module.exports = {
  images: {
    loader: 'imgix',
    path: 'https://ImgApp/imgix.net',
  },
}

การกำหนดค่านี้จะทำให้นักพัฒนาแอปสามารถใช้ URL สัมพัทธ์ในแหล่งที่มาของรูปภาพ และเฟรมเวิร์กจะเชื่อมโยง URL สัมพัทธ์เข้ากับเส้นทาง CDN เพื่อสร้าง URL ที่สมบูรณ์ ระบบรองรับ CDN รูปภาพยอดนิยม เช่น Imgix, Cloudinary และ Akamai สถาปัตยกรรมรองรับการใช้ผู้ให้บริการระบบคลาวด์ที่กำหนดเองโดยใช้ฟังก์ชัน loader ที่กำหนดเองสำหรับแอป

รองรับรูปภาพที่โฮสต์ด้วยตนเอง

อาจมีสถานการณ์ที่เว็บไซต์ไม่สามารถใช้ CDN รูปภาพได้ ในกรณีดังกล่าว คอมโพเนนต์รูปภาพต้องรองรับรูปภาพที่โฮสต์ด้วยตนเอง คอมโพเนนต์รูปภาพ Next.js ใช้เครื่องมือเพิ่มประสิทธิภาพรูปภาพเป็นเซิร์ฟเวอร์รูปภาพในตัวที่มี API คล้าย CDN เครื่องมือเพิ่มประสิทธิภาพจะใช้ Sharp สำหรับการแปลงรูปภาพเวอร์ชันที่ใช้งานจริง หากติดตั้งบนเซิร์ฟเวอร์ ไลบรารีนี้เป็นตัวเลือกที่ดีสำหรับทุกคนที่ต้องการสร้างไปป์ไลน์การเพิ่มประสิทธิภาพรูปภาพของตนเอง

รองรับการโหลดแบบโพรเกรสซีฟ

การโหลดแบบโพรเกรสซีฟเป็นเทคนิคที่ใช้ในการเก็บผู้ใช้ไว้ โดยการแสดงภาพตัวยึดตำแหน่งที่มักจะมีคุณภาพต่ำกว่ามากในขณะที่รูปภาพจริงกำลังโหลด ปรับปรุงประสิทธิภาพที่รับรู้และปรับปรุงประสบการณ์ของผู้ใช้ ซึ่งสามารถใช้ร่วมกับการโหลดแบบ Lazy Loading สำหรับรูปภาพครึ่งหน้าล่างหรือในครึ่งหน้าบนได้

คอมโพเนนต์รูปภาพ Next.js รองรับการโหลดแบบโพรเกรสซีฟสำหรับรูปภาพผ่านคุณสมบัติ placeholder ใช้เป็น LQIP (ตัวยึดตำแหน่งรูปภาพคุณภาพต่ำ) สำหรับแสดงรูปภาพคุณภาพต่ำหรือเบลอในขณะที่รูปภาพจริงโหลดได้

ผลกระทบ

จากการเพิ่มประสิทธิภาพทั้งหมดนี้ทำให้เราพบว่าการใช้คอมโพเนนต์รูปภาพ Next.js ในเวอร์ชันที่ใช้งานจริงประสบความสำเร็จ และยังทำงานร่วมกับชุดซอฟต์แวร์เทคโนโลยีอื่นๆ ในคอมโพเนนต์รูปภาพที่คล้ายกันด้วย

เมื่อ Leboncoin ย้ายข้อมูลฟรอนท์เอนด์ของ JavaScript แบบเดิมไปยัง Next.js พวกเขาก็อัปเกรดไปป์ไลน์รูปภาพเพื่อใช้คอมโพเนนต์รูปภาพ Next.js เช่นกัน ในหน้าเว็บที่ย้ายข้อมูลจาก <img> ไปยังหน้าถัดไป/รูปภาพ LCP ลดลงจาก 2.4 วินาทีเป็น 1.7 วินาที จำนวนไบต์ของรูปภาพที่ดาวน์โหลดทั้งหมดสำหรับหน้าเว็บลดลงจาก 663 KB เป็น 326 KB (โดยมีไบต์รูปภาพที่โหลดแบบ Lazy Loading ประมาณ 100 kB)

บทเรียนที่ได้รับ

ทุกคนที่สร้างแอป Next.js จะได้รับประโยชน์จากการใช้คอมโพเนนต์รูปภาพ Next.js สำหรับการเพิ่มประสิทธิภาพ อย่างไรก็ตาม หากคุณต้องการสร้างนามธรรมด้านประสิทธิภาพที่คล้ายกันสำหรับเฟรมเวิร์กหรือ CMS อื่น ต่อไปนี้คือบทเรียนบางส่วนที่เราได้เรียนรู้ตลอดการดำเนินการซึ่งอาจเป็นประโยชน์

วาล์วความปลอดภัยอาจก่อให้เกิดอันตรายมากกว่าดี

ในการเปิดตัวคอมโพเนนต์รูปภาพ Next.js รุ่นแรก เราได้ระบุแอตทริบิวต์ unsized ที่ช่วยให้นักพัฒนาซอฟต์แวร์ข้ามข้อกำหนดด้านขนาดไปก่อน และใช้รูปภาพที่มีขนาดที่ไม่ระบุได้ เราคิดว่าวิธีนี้จำเป็นในกรณีที่ระบบไม่สามารถรู้ความสูงหรือความกว้างของรูปภาพล่วงหน้าได้ อย่างไรก็ตาม เราพบว่าผู้ใช้แนะนำแอตทริบิวต์ unsized ในปัญหาของ GitHub เป็นวิธีแก้ปัญหาแบบรับทั้งหมดเพื่อแก้ปัญหาเกี่ยวกับข้อกำหนดด้านขนาด แม้จะเป็นกรณีที่อาจแก้ปัญหาในลักษณะที่ไม่ทำให้ CLS แย่ลงก็ตาม หลังจากนั้น เราได้เลิกใช้งานและนำแอตทริบิวต์ unsized ออก

แยกการรบกวนที่เป็นประโยชน์ออกจากความรำคาญโดยไม่มีสาระ

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

อย่างไรก็ตาม คุณสามารถดูวิธีแก้ปัญหาสำหรับอุปสรรคดังกล่าวโดยไม่ส่งผลกระทบต่อประสิทธิภาพการทำงาน ตัวอย่างเช่น ในระหว่างการพัฒนาคอมโพเนนต์รูปภาพ Next.js เราได้รับการร้องเรียนว่าการค้นหาขนาดของรูปภาพที่เก็บไว้ในเครื่องนั้นน่ารำคาญ เราได้เพิ่มการนำเข้าภาพนิ่ง ซึ่งเพิ่มประสิทธิภาพกระบวนการนี้โดยการดึงข้อมูลขนาดรูปภาพในเครื่องโดยอัตโนมัติในเวลาสร้างโดยใช้ปลั๊กอิน Babel

รักษาสมดุลระหว่างฟีเจอร์อำนวยความสะดวกและการเพิ่มประสิทธิภาพการทำงาน

หากคอมโพเนนต์รูปภาพไม่ทำอะไรนอกจากทำให้เกิด "ความติดขัดที่เป็นประโยชน์" ต่อผู้ใช้ นักพัฒนาซอฟต์แวร์มักจะไม่ต้องการใช้ เราพบว่าแม้ว่าฟีเจอร์ด้านประสิทธิภาพ เช่น การปรับขนาดรูปภาพและการสร้างค่า srcset โดยอัตโนมัติจะมีความสำคัญมากที่สุด ฟีเจอร์อำนวยความสะดวกที่นักพัฒนาแอปนำเสนอ เช่น การโหลดแบบ Lazy Loading อัตโนมัติและตัวยึดตำแหน่งเบลอในตัว ก็ช่วยกระตุ้นความสนใจในคอมโพเนนต์รูปภาพ Next.js เช่นกัน

กำหนดแผนกลยุทธ์สำหรับฟีเจอร์ต่างๆ เพื่อกระตุ้นการนำไปใช้

การสร้างโซลูชันที่ใช้งานได้ดีในทุกสถานการณ์นั้นเป็นเรื่องยากมาก คุณอาจจะอยากออกแบบอะไรบางอย่างที่ใช้งานได้ดีสำหรับคน 75% และบอกคนอีก 25% ว่า "ในกรณีเหล่านี้ ส่วนประกอบนี้ไม่เหมาะสำหรับคุณ" ถึงจะเป็นเรื่องยาก

ในทางปฏิบัติ กลยุทธ์นี้อาจไม่สอดคล้องกับเป้าหมายของคุณในฐานะนักออกแบบคอมโพเนนต์ คุณต้องการให้นักพัฒนาซอฟต์แวร์นำคอมโพเนนต์ของคุณไปใช้เพื่อให้ได้รับประโยชน์ด้านประสิทธิภาพ การทำเช่นนี้เป็นเรื่องยากหากมีผู้ใช้จำนวนมากที่ไม่สามารถโยกย้ายและรู้สึกว่าไม่สามารถสนทนาได้ โดยมีแนวโน้มที่จะแสดงความผิดหวัง ซึ่งทำให้เกิดมุมมองในแง่ลบซึ่งส่งผลต่อการรับไปใช้งาน

เราขอแนะนำให้คุณมีแผนกลยุทธ์สำหรับคอมโพเนนต์ที่ครอบคลุมกรณีการใช้งานที่สมเหตุสมผลทั้งหมดในระยะยาว นอกจากนี้ คุณควรระบุในเอกสารประกอบอย่างชัดเจนเกี่ยวกับสิ่งที่ไม่รองรับและเหตุผลในการกำหนดความคาดหวังเกี่ยวกับปัญหาที่คอมโพเนนต์ควรแก้ไข

บทสรุป

การใช้และการเพิ่มประสิทธิภาพรูปภาพมีความซับซ้อน นักพัฒนาแอปต้องหาความสมดุลระหว่างประสิทธิภาพและคุณภาพของรูปภาพ ขณะเดียวกันก็ต้องมอบประสบการณ์ที่ยอดเยี่ยมให้กับผู้ใช้ วิธีนี้ทําให้การเพิ่มประสิทธิภาพรูปภาพเป็นความพยายามในการใช้ต้นทุนสูงแต่ให้ผลกระทบสูง

แทนที่จะต้องทำให้แต่ละแอปต้องแปลกใหม่ทุกครั้ง เราจัดทำเทมเพลตแนวทางปฏิบัติแนะนำที่นักพัฒนาซอฟต์แวร์ เฟรมเวิร์ก และสแต็กเทคโนโลยีอื่นๆ สามารถใช้เป็นข้อมูลอ้างอิงสำหรับการใช้งานของตนเองได้ ประสบการณ์การใช้งานนี้มีประโยชน์จริงๆ เพราะเรารองรับเฟรมเวิร์กอื่นๆ ในคอมโพเนนต์รูปภาพ

คอมโพเนนต์รูปภาพ Next.js ได้รับการปรับปรุงผลลัพธ์ด้านประสิทธิภาพในแอปพลิเคชัน Next.js สำเร็จ จึงช่วยปรับปรุงประสบการณ์ของผู้ใช้ให้ดีขึ้น เราเชื่อว่าโมเดลนี้จะเป็นโมเดลที่ดีซึ่งใช้งานได้ดีในระบบนิเวศที่กว้างขึ้น และเราอยากทราบความคิดเห็นจากนักพัฒนาซอฟต์แวร์ที่ต้องการนำโมเดลนี้ไปใช้ในโครงการของพวกเขา