การปรับให้เข้ากับผู้ใช้ด้วยคำแนะนำสำหรับไคลเอ็นต์

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

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

ทั้งหมดนี้เป็นเรื่องของการเจรจาต่อรองเนื้อหา

คำแนะนำสำหรับไคลเอ็นต์เป็นอีกวิธีหนึ่งของการเจรจาต่อรองเนื้อหา ซึ่งหมายถึงการเปลี่ยนแปลงการตอบสนองเนื้อหาตามส่วนหัวของคำขอเบราว์เซอร์

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

Accept: image/webp,image/apng,image/*,*/*;q=0.8

แม้ว่าเบราว์เซอร์ทั้งหมดจะรองรับรูปแบบรูปภาพ เช่น JPEG, PNG และ GIF แต่ Accept จะบอกในกรณีนี้ว่าเบราว์เซอร์ยังรองรับ WebP และ APNG ด้วย เราใช้ข้อมูลนี้เพื่อเจรจาต่อรองประเภทรูปภาพที่ดีที่สุดสำหรับแต่ละเบราว์เซอร์ได้ดังนี้

<?php
// Check Accept for an "image/webp" substring.
$webp = stristr($_SERVER["HTTP_ACCEPT"], "image/webp") !== false ? true : false;

// Set the image URL based on the browser's WebP support status.
$imageFile = $webp ? "whats-up.webp" : "whats-up.jpg";
?>
<img src="<?php echo($imageFile); ?>" alt="I'm an image!">

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

การเลือกใช้

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

Accept-CH: Viewport-Width, Downlink

ค่าสำหรับ Accept-CH คือรายการที่คั่นด้วยคอมมาของคำแนะนำที่ขอซึ่งเว็บไซต์จะใช้ในการกำหนดผลลัพธ์สำหรับคำขอทรัพยากรที่ตามมา เมื่อไคลเอ็นต์อ่านส่วนหัวนี้ ระบบจะแจ้งว่า "เว็บไซต์นี้ต้องการคำแนะนำสำหรับไคลเอ็นต์ Viewport-Width และ Downlink" ไม่ต้องกังวลเกี่ยวกับคำแนะนำที่เฉพาะเจาะจงเหล่านั้น เราจะพูดถึงเรื่องนี้ในอีกสักครู่

คุณตั้งค่าส่วนหัวของการเลือกรับเหล่านี้เป็นภาษาแบ็กเอนด์ใดก็ได้ เช่น คุณสามารถใช้ฟังก์ชัน header ของ PHP นอกจากนี้ คุณยังตั้งค่าส่วนหัวของการเลือกใช้เหล่านี้ได้ด้วยแอตทริบิวต์ http-equiv ในแท็ก <meta> ดังนี้

<meta http-equiv="Accept-CH" content="Viewport-Width, Downlink" />

คำแนะนำสำหรับไคลเอ็นต์ทั้งหมด

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

คำแนะนำอุปกรณ์

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

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

ขนาดที่แท้จริง: ขนาดจริงของทรัพยากรสื่อ ตัวอย่างเช่น หากคุณเปิดรูปภาพใน Photoshop ขนาดที่แสดงในกล่องโต้ตอบขนาดรูปภาพจะอธิบายขนาดที่แท้จริงของรูปภาพ

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

<img
  src="whats-up-1x.png"
  srcset="whats-up-2x.png 2x, whats-up-1x.png 1x"
  alt="I'm that image you wanted."
/>

สมมติว่าขนาดที่แท้จริงของรูปภาพ 1x ในกรณีนี้คือ 320x240 และขนาดที่แท้จริงของรูปภาพ 2x คือ 640x480 หากมาร์กอัปนี้ได้รับการแยกวิเคราะห์โดยไคลเอ็นต์ที่ติดตั้งในอุปกรณ์ที่มีอัตราส่วนพิกเซลของหน้าจออุปกรณ์เท่ากับ 2 (เช่น หน้าจอ Retina) ระบบจะขอรูปภาพ 2x ขนาดที่แท้จริงที่ปรับตามความหนาแน่นของรูปภาพ 2x คือ 320x240 เนื่องจาก 640x480 หารด้วย 2 คือ 320x240

ขนาดภายนอก: ขนาดของทรัพยากรสื่อหลังจากใช้ CSS และปัจจัยเลย์เอาต์อื่นๆ (เช่น แอตทริบิวต์ width และ height) กับทรัพยากรดังกล่าว สมมติว่าคุณมีองค์ประกอบ <img> ที่โหลดรูปภาพซึ่งมีขนาดที่แท้จริงที่แก้ไขความหนาแน่นแล้วเป็น 320x240 แต่ก็มีพร็อพเพอร์ตี้ CSS width และ height ที่มีค่าเป็น 256px และ 192px ตามลำดับ ในตัวอย่างนี้ ขนาดภายนอกขององค์ประกอบ <img> นั้นจะกลายเป็น 256x192

ภาพแสดงขนาดภายในเทียบกับขนาดภายนอก กล่องขนาด 320x240 พิกเซลจะแสดงพร้อมป้ายกำกับ INTRINSIC SIZE ภายในมีกล่องขนาดเล็กกว่า 256x192 พิกเซล ซึ่งแสดงถึงองค์ประกอบ img ของ HTML ที่ใช้ CSS กล่องนี้มีป้ายกำกับว่า EXTRINSIC SIZE ทางด้านขวาคือช่องที่มี CSS ซึ่งใช้กับองค์ประกอบที่แก้ไขเลย์เอาต์ขององค์ประกอบ img เพื่อให้ขนาดภายนอกแตกต่างจากขนาดภายใน
รูปที่ 1 ภาพแสดงขนาดภายในเทียบกับขนาดภายนอก รูปภาพจะมีขนาดภายนอกหลังจากใช้ปัจจัยเลย์เอาต์กับรูปภาพแล้ว ในกรณีนี้ การใช้กฎ CSS ของ width: 256px; และ height: 192px; จะเปลี่ยนรูปภาพขนาด 320x240 ที่มีขนาดตามเนื้อหาให้เป็นรูปภาพขนาด 256x192 ที่มีขนาดตามภายนอก

เมื่อทราบคำศัพท์บางคำแล้ว เรามาดูรายการคำแนะนำสำหรับไคลเอ็นต์เฉพาะอุปกรณ์ที่พร้อมให้คุณใช้งานกัน

Viewport-Width

Viewport-Width คือความกว้างของวิวพอร์ตของผู้ใช้ในหน่วยพิกเซล CSS ดังนี้

Viewport-Width: 320

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

DPR

DPR ซึ่งย่อมาจากอัตราส่วนพิกเซลของอุปกรณ์ จะรายงานอัตราส่วนของพิกเซลจริงต่อพิกเซล CSS ของหน้าจอผู้ใช้ ดังนี้

DPR: 2

คำแนะนำนี้มีประโยชน์เมื่อเลือกแหล่งที่มาของรูปภาพที่สอดคล้องกับความหนาแน่นพิกเซลของหน้าจอ (เช่น ตัวบ่งชี้ x ในแอตทริบิวต์ srcset)

ความกว้าง

คำแนะนำ Width จะปรากฏในคำขอทรัพยากรรูปภาพที่เริ่มทำงานโดยแท็ก <img> หรือ <source> โดยใช้แอตทริบิวต์ sizes sizes จะบอกเบราว์เซอร์ว่าขนาดภายนอกของทรัพยากรจะเป็นเท่าใด Width จะใช้ขนาดภายนอกนั้นเพื่อขอรูปภาพที่มีขนาดภายในที่เหมาะสมที่สุดสำหรับเลย์เอาต์ปัจจุบัน

ตัวอย่างเช่น สมมติว่าผู้ใช้ขอหน้าเว็บที่มีหน้าจอกว้าง 320 CSS พิกเซลและมี DPR เท่ากับ 2 อุปกรณ์จะโหลดเอกสารที่มีองค์ประกอบ <img> ซึ่งมีค่าแอตทริบิวต์ sizes เป็น 85vw (เช่น 85% ของความกว้างวิวพอร์ตสำหรับหน้าจอทุกขนาด) หากเลือกใช้คำแนะนำ Width ไคลเอ็นต์จะส่งคำแนะนำ Width นี้ไปยังเซิร์ฟเวอร์พร้อมกับคำขอ src ของ <img> ดังนี้

Width: 544

ในกรณีนี้ ไคลเอ็นต์จะบอกใบ้เซิร์ฟเวอร์ว่าความกว้างที่แท้จริงที่เหมาะสมที่สุดสำหรับรูปภาพที่ขอคือ 85% ของความกว้างวิวพอร์ต (272 พิกเซล) คูณด้วย DPR ของหน้าจอ (2) ซึ่งเท่ากับ 544 พิกเซล

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

Content-DPR

แม้ว่าคุณจะทราบอยู่แล้วว่าหน้าจอมีอัตราส่วนพิกเซลของอุปกรณ์ แต่ทรัพยากรก็มีอัตราส่วนพิกเซลของตัวเองด้วย ในกรณีการใช้งานการเลือกทรัพยากรที่ง่ายที่สุด อัตราส่วนพิกเซลระหว่างอุปกรณ์และทรัพยากรอาจเหมือนกัน แต่! ในกรณีที่ใช้ทั้งส่วนหัว DPR และ Width ขนาดภายนอกของทรัพยากรอาจทำให้เกิดสถานการณ์ที่ทั้ง 2 ส่วนหัวแตกต่างกัน นี่คือจุดที่คำใบ้ Content-DPR เข้ามามีบทบาท

Content-DPR ไม่เหมือนกับคำแนะนำอื่นๆ ของไคลเอ็นต์ตรงที่ไม่ใช่ส่วนหัวคำขอที่เซิร์ฟเวอร์จะใช้ แต่เป็นส่วนหัวการตอบกลับที่เซิร์ฟเวอร์ต้องส่งเมื่อใดก็ตามที่มีการใช้คำแนะนำ DPR และ Width เพื่อเลือกทรัพยากร ค่าของ Content-DPR ควรเป็นผลลัพธ์ของสมการนี้

Content-DPR = [ขนาดทรัพยากรรูปภาพที่เลือก] / ([Width] / [DPR])

เมื่อส่งส่วนหัวของคำขอ Content-DPR เบราว์เซอร์จะทราบวิธีปรับขนาดรูปภาพที่ระบุสำหรับอัตราส่วนพิกเซลของอุปกรณ์ของหน้าจอและเลย์เอาต์ หากไม่มีแอตทริบิวต์นี้ รูปภาพอาจปรับขนาดไม่ถูกต้อง

Device-Memory

ในทางเทคนิคแล้ว Device-Memory เป็นส่วนหนึ่งของ Device Memory API ซึ่งจะแสดงปริมาณหน่วยความจำโดยประมาณที่อุปกรณ์ปัจจุบันมีในหน่วย GiB ดังนี้

Device-Memory: 2

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

คำแนะนำเกี่ยวกับเครือข่าย

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

RTT

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

RTT: 125

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

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

Downlink: 2.5

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

ECT

คำแนะนำ ECT ย่อมาจาก Effective Connection Type (ประเภทการเชื่อมต่อที่มีประสิทธิภาพ) ค่าของตัวแปรนี้คือค่าหนึ่งในรายการประเภทการเชื่อมต่อที่แจกแจงไว้ ซึ่งแต่ละค่าจะอธิบายการเชื่อมต่อภายในช่วงที่ระบุของทั้งค่า RTT และ Downlink

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

ECT: 2g

ค่าที่ถูกต้องสำหรับ ECT คือ 4g, 3g, 2g และ slow-2g คุณสามารถใช้คำแนะนำนี้เป็นจุดเริ่มต้นในการประเมินคุณภาพการเชื่อมต่อ แล้วปรับแต่งโดยใช้คำแนะนำ RTT และ Downlink

Save-Data

Save-Data ไม่ได้เป็นคำแนะนำที่อธิบายสภาพเครือข่ายมากนัก แต่เป็นค่ากำหนดของผู้ใช้ที่ระบุว่าหน้าเว็บควรส่งข้อมูลน้อยลง

ฉันชอบจัดประเภท Save-Data เป็นคำแนะนำเกี่ยวกับเครือข่าย เพราะหลายๆ สิ่งที่คุณจะทำกับคำแนะนำนี้คล้ายกับคำแนะนำเกี่ยวกับเครือข่ายอื่นๆ ผู้ใช้อาจเปิดใช้ฟีเจอร์นี้ในสภาพแวดล้อมที่มีเวลาในการตอบสนองสูง/แบนด์วิดท์ต่ำด้วย คำแนะนำนี้เมื่อปรากฏจะมีลักษณะดังนี้เสมอ

Save-Data: on

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

ลองนำทุกอย่างมารวมกัน

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

รูปภาพที่ปรับเปลี่ยนตามอุปกรณ์

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

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

ซึ่งคำแนะนำสำหรับไคลเอ็นต์จะช่วยลดความซับซ้อนนี้ได้ การเจรจาต่อรองการตอบกลับรูปภาพด้วยคำแนะนำสำหรับไคลเอ็นต์อาจมีลักษณะดังนี้

  1. หากเกี่ยวข้องกับเวิร์กโฟลว์ของคุณ ให้เลือกการปรับแต่งรูปภาพ (เช่น รูปภาพที่กำกับศิลป์) ก่อนโดยดูคำแนะนำ Viewport-Width
  2. เลือกความละเอียดของรูปภาพโดยตรวจสอบคำแนะนำ Width และคำแนะนำ DPR แล้วเลือกแหล่งที่มาที่เหมาะกับขนาดเลย์เอาต์และความหนาแน่นของหน้าจอของรูปภาพ (คล้ายกับวิธีการทำงานของข้อบ่งชี้ x และ w ใน srcset)
  3. เลือกรูปแบบไฟล์ที่เหมาะสมที่สุดที่เบราว์เซอร์รองรับ (ซึ่ง Accept ช่วยเราได้ในเบราว์เซอร์ส่วนใหญ่)

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

<picture>
  <source
    srcset="
      company-photo-256w.webp   256w,
      company-photo-512w.webp   512w,
      company-photo-768w.webp   768w,
      company-photo-1024w.webp 1024w,
      company-photo-1280w.webp 1280w
    "
    type="image/webp"
  />
  <img
    srcset="
      company-photo-256w.jpg   256w,
      company-photo-512w.jpg   512w,
      company-photo-768w.jpg   768w,
      company-photo-1024w.jpg 1024w,
      company-photo-1280w.jpg 1280w
    "
    src="company-photo-256w.jpg"
    sizes="(min-width: 560px) 251px, 88.43vw"
    alt="The Sconnie Timber Staff!"
  />
</picture>

ฉันลดจำนวนลงได้ตามการรองรับของเบราว์เซอร์แต่ละรายการดังนี้

<img
  src="/image/sizes:true/company-photo.jpg"
  sizes="(min-width: 560px) 251px, 88.43vw"
  alt="SAY CHEESY PICKLES."
/>

ในตัวอย่างนี้ URL /image เป็นสคริปต์ PHP ตามด้วยพารามิเตอร์ที่เขียนใหม่โดย mod_rewrite โดยจะใช้ชื่อไฟล์รูปภาพและพารามิเตอร์เพิ่มเติมเพื่อช่วยให้สคริปต์แบ็กเอนด์เลือกรูปภาพที่ดีที่สุดในเงื่อนไขที่ระบุ

เราคาดว่าคำถามแรกของคุณคือ "แต่นี่ไม่ใช่แค่การนำ <picture> และ srcset ไปใช้ใหม่ในแบ็กเอนด์ใช่ไหม"

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

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

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

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

การช่วยเหลือผู้ใช้ในเครือข่ายที่ช้า

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

ในกรณีที่เว็บไซต์ของ Sconnie Timber มีปัญหา เราจะดำเนินการเพื่อลดภาระเมื่อเครือข่ายทำงานช้า โดยตรวจสอบส่วนหัว Save-Data, ECT, RTT และ Downlink ในโค้ดแบ็กเอนด์ เมื่อดำเนินการเสร็จแล้ว เราจะสร้างคะแนนคุณภาพเครือข่ายที่สามารถใช้เพื่อพิจารณาว่าเราควรแทรกแซงเพื่อประสบการณ์ของผู้ใช้ที่ดีขึ้นหรือไม่ คะแนนเครือข่ายนี้อยู่ระหว่าง 0 ถึง 1 โดย 0 คือคุณภาพเครือข่ายที่แย่ที่สุด และ 1 คือคุณภาพเครือข่ายที่ดีที่สุด

ก่อนอื่น เราจะตรวจสอบว่ามี Save-Data หรือไม่ หากเป็นเช่นนั้น ระบบจะตั้งค่าคะแนนเป็น 0 เนื่องจากเราถือว่าผู้ใช้ต้องการให้เราทำทุกอย่างที่จำเป็นเพื่อให้ประสบการณ์การใช้งานเบาลงและเร็วขึ้น

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

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

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

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

Waterfall ของ WebPagetest ของเว็บไซต์ Sconnie Timber ที่โหลดทรัพยากรทั้งหมดในการเชื่อมต่อเครือข่ายที่ช้า
รูปที่ 3 เว็บไซต์ที่ใช้ทรัพยากรจำนวนมากในการโหลดรูปภาพ สคริปต์ และแบบอักษรในการเชื่อมต่อที่ช้า

และตอนนี้เป็นแผนภาพ Waterfall สำหรับเว็บไซต์เดียวกันในการเชื่อมต่อที่ช้าเหมือนกัน แต่ครั้งนี้เว็บไซต์ใช้คำแนะนำสำหรับไคลเอ็นต์เพื่อกำจัดทรัพยากรหน้าเว็บที่ไม่สำคัญ

Waterfall ของ WebPagetest ของเว็บไซต์ Sconnie Timber ที่ใช้คำแนะนำสำหรับไคลเอ็นต์เพื่อตัดสินใจไม่โหลดทรัพยากรที่ไม่สำคัญในการเชื่อมต่อเครือข่ายที่ช้า
รูปที่ 4 เว็บไซต์เดียวกันในการเชื่อมต่อเดียวกัน แต่ไม่รวมทรัพยากรที่ "มีก็ดี" เพื่อให้โหลดได้เร็วขึ้น

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

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

// Set the ECT value to "4g" by default.
$ect = isset($_SERVER["HTTP_ECT"]) ? $_SERVER["HTTP_ECT"] : "4g";

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

อย่าลืมเรื่องแคช

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

Vary: DPR, Width

อย่างไรก็ตาม มีข้อควรระวังสำคัญคือ คุณไม่ควรVaryการตอบกลับที่แคชได้ในส่วนหัวที่เปลี่ยนแปลงบ่อย (เช่น Cookie) เนื่องจากจะทำให้ทรัพยากรเหล่านั้นแคชไม่ได้อย่างมีประสิทธิภาพ เมื่อทราบเช่นนี้แล้ว คุณอาจต้องการหลีกเลี่ยง Varyการใช้ส่วนหัวของคำแนะนำสำหรับไคลเอ็นต์ เช่น RTT หรือ Downlink เนื่องจากเป็น ปัจจัยการเชื่อมต่อที่อาจเปลี่ยนแปลงบ่อยครั้ง หากต้องการแก้ไขการตอบกลับในส่วนหัวเหล่านั้น ให้พิจารณาคีย์เฉพาะส่วนหัว ECT ซึ่งจะช่วยลดการไม่พบแคช

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

คำแนะนำสำหรับไคลเอ็นต์ใน Service Worker

การเจรจาต่อรองเนื้อหาไม่ได้มีไว้สำหรับเซิร์ฟเวอร์เท่านั้นอีกต่อไป เนื่องจาก Service Worker ทำหน้าที่เป็นพร็อกซีระหว่างไคลเอ็นต์และเซิร์ฟเวอร์ คุณจึงควบคุมวิธีส่งทรัพยากรผ่าน JavaScript ได้ ซึ่งรวมถึงคำแนะนำสำหรับไคลเอ็นต์ ในเหตุการณ์ fetch ของ Service Worker คุณสามารถใช้เมธอด request.headers.get ของออบเจ็กต์ event เพื่ออ่านส่วนหัวของคำขอของทรัพยากรได้ดังนี้

self.addEventListener('fetch', (event) => {
  let dpr = event.request.headers.get('DPR');
  let viewportWidth = event.request.headers.get('Viewport-Width');
  let width = event.request.headers.get('Width');

  event.respondWith(
    (async function () {
      // Do what you will with these hints!
    })(),
  );
});

ส่วนหัวของคำแนะนำสำหรับไคลเอ็นต์ที่คุณเลือกใช้จะอ่านได้ในลักษณะนี้ แต่ก็ยังมีวิธีอื่นๆ ที่คุณจะได้รับข้อมูลบางส่วนนี้ คุณสามารถอ่านคำแนะนำเฉพาะเครือข่ายได้ในพร็อพเพอร์ตี้ JavaScript ที่เทียบเท่าเหล่านี้ในออบเจ็กต์ navigator

คำแนะนำสำหรับไคลเอ็นต์ เทียบเท่า JS
`ECT` `navigator.connection.effectiveType`
`RTT` `navigator.connection.rtt`
`Save-Data` `navigator.connection.saveData`
`Downlink` `navigator.connection.downlink`
`Device-Memory` `navigator.deviceMemory`
ปลั๊กอิน Imagemin สำหรับประเภทไฟล์

เนื่องจาก API เหล่านี้ไม่พร้อมใช้งานในทุกที่ คุณจึงต้องตรวจสอบฟีเจอร์กับผู้ให้บริการ in ดังนี้

if ('connection' in navigator) {
  // Work with netinfo API properties in JavaScript!
}

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

ใกล้จะเสร็จแล้ว

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

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

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

แหล่งข้อมูล

ขอขอบคุณ Ilya Grigorik, Eric Portis, Jeff Posnick, Yoav Weiss และ Estelle Weyl สำหรับความคิดเห็นและการแก้ไขที่มีคุณค่าในบทความนี้