วิธีปิดการสร้างรูป -scaled ใน WordPress (big_image_size_threshold)
แก้ปัญหารูป WordPress ดูไม่คม ด้วยการเพิ่มหรือยกเลิกเพดาน 2560px ผ่านฟิลเตอร์ big_image_size_threshold และดูว่าทำไมขั้นตอนอัพโหลดใหม่ถึงเป็นขั้นที่คนมักข้าม
เผยแพร่แล้ว
เพิ่มฟิลเตอร์บน big_image_size_threshold ที่คืนค่า false แล้ว WordPress จะหยุดสร้างสำเนา -scaled ตอนอัพโหลด ถ้าคืนค่าเป็นตัวเลขแทน ก็เท่ากับขยับเพดานให้สูงขึ้นแทนที่จะเอาออก ทั้งสองแบบใส่ได้ใน functions.php หรือ mu-plugin เล็ก ๆ สักไฟล์ และทั้งสองแบบมีผลเฉพาะกับไฟล์ที่อัพโหลดหลังจากฟิลเตอร์เริ่มทำงานแล้วเท่านั้น
// Disable the cap entirely — no -scaled copies at all.
add_filter( 'big_image_size_threshold', '__return_false' );
// Or just raise it. Longest edge, in pixels.
add_filter( 'big_image_size_threshold', function () {
return 3840;
} );
WordPress กำลังทำอะไรอยู่จริง ๆ
ตั้งแต่ WordPress 5.3 เป็นต้นมา ทุกไฟล์ที่อัพโหลดจะถูกวัดที่ด้านยาวที่สุด ถ้าด้านนั้นใหญ่กว่า big_image_size_threshold — ค่าเริ่มต้นคือ 2560px — WordPress จะเข้ารหัสรูปใหม่ให้ลดลงมาที่ขีดจำกัดนั้น บันทึกเป็น your-photo-scaled.jpg แล้วเขียน metadata ของไฟล์แนบใหม่ ให้ขนาด full ชี้ไปที่สำเนาที่ถูกย่อแทน
ไฟล์ต้นฉบับไม่ได้ถูกลบ มันยังอยู่บนดิสก์ในชื่อไฟล์เดิม ถูกบันทึกไว้ใน metadata ของไฟล์แนบ และเรียกถึงได้ใน PHP ผ่าน wp_get_original_image_path() แต่ไม่มีอะไรบนหน้าเว็บเสิร์ฟมันเลย ไม่ว่าจะเป็น block editor, srcset หรือภาพตัวอย่างในคลังสื่อ มันแค่นอนอยู่ตรงนั้นในฐานะสำเนาเก็บถาวร
ทุกอย่างที่ตามมาหลังจากนั้นถูกสร้างจากไฟล์ที่ถูกย่อ ไม่ใช่จากไฟล์ที่คุณอัพโหลด:
| ขนาด | สร้างจากไฟล์ไหน |
|---|---|
full | สำเนา -scaled |
large, medium_large, medium, thumbnail | สำเนา -scaled |
ขนาดที่กำหนดเองผ่าน add_image_size | สำเนา -scaled |
ขนาดของธีมและปลั๊กอิน เช่น woocommerce_thumbnail | สำเนา -scaled |
ตัวเลือกใน srcset | สำเนา -scaled |
ข้อเท็จจริงข้อเดียวนี้แหละที่ทำให้หลายคนพลาดกันมานักต่อนัก
ทำไมนี่ถึงเป็นสาเหตุยอดฮิตของ “รูปคมชัดของฉันดูไม่คมเลย”
มีสองอย่างเกิดขึ้นพร้อมกัน และมีแค่อย่างเดียวที่เห็นได้ชัด
อย่างที่ชัดเจนคือความละเอียด คุณอัพโหลดภาพถ่าย 4000px มาทำ hero เต็มความกว้าง WordPress ส่งภาพ 2560px ให้เบราว์เซอร์ บนจอมาตรฐานที่แสดงผลในกล่องกว้าง 1600px ไม่มีใครสังเกตเห็น แต่บนจอ retina 2x กล่องนั้นต้องการพิกเซลจริงราว 3200 พิกเซล แต่ได้มา 2560 เบราว์เซอร์จึงขยายส่วนที่ขาดขึ้นมา ขอบเลยดูฟุ้ง รายละเอียดเละ ตัวหนังสือในรูปกลายเป็นเบลอ
อย่างที่ไม่ชัดเจนคือการเข้ารหัสใหม่ สำเนา -scaled ไม่ใช่การครอปแบบไม่สูญเสียคุณภาพจากไฟล์ของคุณ WordPress ถอดรหัสไฟล์ที่คุณอัพโหลด ย่อขนาด แล้วบีบอัดใหม่ด้วยค่าคุณภาพ JPEG ของตัวเอง ถ้าไฟล์ต้นฉบับของคุณเป็น JPEG ที่ถูกบีบอัดมาแล้วจาก Lightroom หรือจากมือถือ นั่นคือการเข้ารหัสรุ่นที่สอง — อาร์ติแฟกต์จากการบีบอัดซ้อนทับอาร์ติแฟกต์เดิม รายละเอียดเล็ก ๆ เกรนฟิล์ม และไล่เฉดสีเรียบ ๆ จะโดนหนักที่สุด คุณเห็นผลนี้ได้แม้ในกรณีที่ขนาดพิกเซลดูเพียงพอแล้ว
ยืนยันให้แน่ก่อนเปลี่ยนอะไร เปิดรูปในแท็บใหม่แล้วอ่านชื่อไฟล์ใน URL ถ้าเห็น -scaled.jpg แปลว่าเพดานทำงาน แต่ถ้าเป็นคำต่อท้ายที่บอกขนาดอย่าง -1536x1024.jpg นั่นคนละเรื่องกัน — srcset เลือกไฟล์ระดับกลางที่เล็กเกินไป และฟิลเตอร์ threshold ช่วยอะไรตรงนั้นไม่ได้
บนเซิร์ฟเวอร์:
find wp-content/uploads -name '*-scaled.*' | wc -l
ถ้าตัวเลขนั้นสูง แปลว่าเพดานได้กำหนดรูปร่างของคลังรูปทั้งคลังของคุณมาตลอด
คุณยังลากไฟล์ไปวางใน เครื่องมือปิดการสร้างรูป scaled เพื่อดูได้ว่าไฟล์ต้นทางไฟล์หนึ่งจะไปชนเพดานหรือไม่ และสำเนาที่ถูกย่อจะออกมาขนาดเท่าไหร่ ก่อนที่คุณจะตัดสินใจตั้งค่าจริง
สิ่งที่ต้องแลก พูดกันตรง ๆ
บทความส่วนใหญ่บอกว่าการปิดเพดานจะเปลืองพื้นที่ดิสก์ นั่นกลับหัวกลับหาง และควรพูดให้ชัด
พื้นที่ดิสก์ต่อรูปหนึ่งภาพลดลงเล็กน้อย เมื่อเปิด threshold ไว้ WordPress เก็บทั้งไฟล์ต้นฉบับ และ สำเนาขนาดใหญ่ที่ถูกย่อ เมื่อปิด คุณเก็บแค่ไฟล์ต้นฉบับ หนึ่งไฟล์แทนที่จะเป็นสองไฟล์
แบนด์วิดท์และน้ำหนักหน้าเว็บเพิ่มขึ้น บางทีเพิ่มเยอะ เมื่อปิดเพดาน full คือไฟล์ที่คุณอัพโหลดแบบไม่ถูกแตะ อะไรก็ตามที่ลิงก์หรือแสดงขนาด full — lightbox, ปลั๊กอินแกลเลอรี, ลิงก์ “ดูภาพต้นฉบับ”, ธีมที่เรียก full มาทำ hero — ตอนนี้จะส่งไฟล์ที่อาจหนัก 6MB แทนที่จะเป็น 900KB บนมือถือนั่นคือปัญหา Largest Contentful Paint ของจริง และ CDN สำหรับรูปก็ไม่ได้ช่วยเสมอไป เพราะบางเจ้าจะปล่อยผ่านถ้าไฟล์ใหญ่เกินขีดจำกัด
หน่วยความจำตอนอัพโหลดสูงขึ้น การย่อรูป 6000px ใน PHP กินหน่วยความจำมากกว่ารูป 2560px อยู่พอสมควร บนโฮสต์แชร์ราคาถูกที่ตั้ง memory limit ของ PHP ไว้ต่ำ การปิดเพดานมีโอกาสทำให้เริ่มอัพโหลดไม่สำเร็จ หรือสร้างภาพย่อได้ไม่ครบ การขยับ threshold เป็น 3840 แทนที่จะเอาออกทั้งหมด คือเวอร์ชันที่ปลอดภัยกว่าของการเปลี่ยนแปลงเดียวกัน
เพราะแบบนี้ ค่าเริ่มต้นที่สมเหตุสมผลสำหรับเว็บส่วนใหญ่จึงเป็นการเพิ่มตัวเลข ไม่ใช่การเอาออก การเอาออกจะถูกต้องก็ต่อเมื่อคุณกำลังเสิร์ฟรูปที่ต้องการความละเอียดเต็มจริง ๆ เช่น แกลเลอรีคุณภาพระดับงานพิมพ์ ฟีเจอร์ซูมสินค้า ภาพถ่ายสถาปัตยกรรม หรืออะไรก็ตามที่ผู้ใช้ถูกคาดหวังให้เข้าไปพิจารณาภาพต้นฉบับ
วิธีนำการเปลี่ยนแปลงไปใช้ให้ถูกต้อง
1. วางฟิลเตอร์ไว้ในที่ที่มันอยู่รอด functions.php ใน child theme ก็ใช้ได้ แต่ mu-plugin ไฟล์เดียวดีกว่า เพราะการเปลี่ยนธีมจะไม่ทำให้มันหายไปแบบเงียบ ๆ
<?php
/**
* Plugin Name: Raise big image threshold
*/
add_filter( 'big_image_size_threshold', function () {
return 3840;
} );
2. อัพโหลดรูปที่ได้รับผลกระทบใหม่ นี่คือขั้นตอนที่คนมักข้าม แล้วสรุปว่าฟิลเตอร์ไม่ทำงาน threshold ถูกประเมินครั้งเดียวคือตอนอัพโหลด ไฟล์แนบที่มีอยู่แล้วจะเก็บ metadata เดิมไว้ตลอดไป ให้ลบไฟล์แนบแล้วอัพโหลดใหม่ จากนั้นแก้การอ้างอิงในโพสต์ของคุณ
3. อย่าคาดหวังว่าการ regenerate ภาพย่อจะช่วยกู้อะไรได้ wp media regenerate ผ่าน WP-CLI จะสร้างขนาดระดับกลางขึ้นมาใหม่จากไฟล์ที่ metadata เรียกว่าไฟล์ full ซึ่งสำหรับรูปที่ถูกลดขนาดไปแล้วก็คือสำเนา -scaled นั่นเอง มันคืนรายละเอียดที่ถูกทิ้งไปแล้วไม่ได้ มีประโยชน์ในฐานะการเก็บกวาดหลังอัพโหลดใหม่ แต่ไร้ประโยชน์ถ้าใช้เป็นวิธีแก้ปัญหาโดด ๆ
4. ตรวจผลลัพธ์ อย่าเดา หลังอัพโหลดใหม่แล้ว เปิดรูปบนหน้าเว็บแล้วอ่านชื่อไฟล์อีกครั้ง ถ้าไม่มี -scaled แปลว่าฟิลเตอร์ทำงานอยู่
เมื่อการปิดเพดานเป็นทางเลือกที่ผิด
ถ้ารูปต้นทางของคุณเล็กกว่า 2560px อยู่แล้วแต่ยังดูไม่คม แปลว่า threshold ไม่เคยเกี่ยวข้องเลย ปัญหาคือกล่องแสดงผลใหญ่กว่าจำนวนพิกเซลที่มีอยู่ และคำตอบคือไฟล์ต้นทางที่ใหญ่ขึ้นหรือกล่องที่เล็กลง ไม่ใช่ฟิลเตอร์ตัวนี้
ถ้าชื่อไฟล์ที่ถูกเสิร์ฟมีคำต่อท้ายบอกขนาดแทนที่จะเป็น -scaled แปลว่า srcset เลือกไฟล์ตัวเล็กมา นั่นมักเกิดจากความไม่ตรงกันระหว่างความกว้างเนื้อหาที่ธีมประกาศไว้ กับกล่องที่รูปถูกแสดงจริง การปิดเพดานไม่เปลี่ยนอะไรตรงนั้นเลย
และถ้ามีปลั๊กอินเขียนทับ src ของคุณให้ชี้ไปที่ตัวปรับแต่งรูปหรือพร็อกซี CDN ทั้งหมดนี้ยังใช้ไม่ได้จนกว่าคุณจะไปดูว่าพร็อกซีตัวนั้นเสิร์ฟอะไรอยู่ ลองเทียบสิ่งที่ WordPress ควรจะสร้างกับสิ่งที่เบราว์เซอร์โหลดมาจริง เมื่อสองอย่างนี้ไม่ตรงกัน ให้ไปดูว่ามีอะไรคั่นอยู่ตรงกลาง
FAQ
คำถาม
จะปิดการสร้างรูป scaled ใน WordPress ได้อย่างไร
เพิ่มฟิลเตอร์บน big_image_size_threshold ที่คืนค่า false ใส่ไว้ใน functions.php หรือ mu-plugin เล็ก ๆ สักไฟล์ การคืนค่า false จะปิดเพดานทิ้งไปเลย ไฟล์ที่อัพโหลดจึงคงขนาดต้นฉบับไว้และไม่มีการสร้างสำเนา -scaled ส่วนการคืนค่าเป็นตัวเลขอย่างเช่น 3840 คือการขยับเพดานให้สูงขึ้น ไม่ใช่การเอาเพดานออก
คำต่อท้าย -scaled ในชื่อไฟล์ของ WordPress คืออะไร
มันบอกว่านี่คือสำเนาที่ WordPress เข้ารหัสใหม่ เพราะไฟล์ที่คุณอัพโหลดมีด้านยาวเกิน 2560px สำเนานั้นจะกลายเป็นขนาด full ในทุกจุดของเว็บ ไฟล์ต้นฉบับยังอยู่บนดิสก์ในชื่อปกติ แต่ไม่มีอะไรบนหน้าเว็บลิงก์ไปหามัน และทุกภาพย่อกับทุกตัวเลือกใน srcset ถูกสร้างจากสำเนา scaled นั้น
การปิด scaled images ทำให้เปลืองพื้นที่ดิสก์มากขึ้นไหม
ต่อรูปหนึ่งภาพมักใช้พื้นที่น้อยลงนิดหน่อย เพราะ WordPress เลิกเขียนไฟล์ขนาดใหญ่อีกไฟล์ควบคู่กับต้นฉบับ ต้นทุนจริงอยู่ที่แบนด์วิดท์ ไม่ใช่พื้นที่จัดเก็บ เมื่อปิดเพดานแล้ว อะไรก็ตามที่ลิงก์ไปยังขนาด full จะเสิร์ฟไฟล์ต้นฉบับที่ไม่ถูกแตะเลย ซึ่งอาจหนักหลายเมกะไบต์บนเน็ตมือถือ
ปิด threshold แล้วรูปที่เบลออยู่แล้วจะกลับมาคมไหม
ไม่ ฟิลเตอร์นี้มีผลกับไฟล์ที่อัพโหลดใหม่เท่านั้น รูปที่อยู่ในคลังแล้วยังมี metadata ชี้ไปที่สำเนา scaled ของมัน และการ regenerate ภาพย่อก็สร้างขนาดต่าง ๆ จากไฟล์ที่ถูกลดขนาดไปแล้วตัวเดิม ถ้าอยากได้ความละเอียดคืน ต้องลบไฟล์แนบนั้นแล้วอัพโหลดใหม่หลังจากฟิลเตอร์ทำงานแล้ว
2560px เป็นค่า threshold ที่ควรใช้ต่อไปหรือเปล่า
สำหรับเว็บเนื้อหาส่วนใหญ่ ใช่ ต้นฉบับขนาด 2560px ครอบคลุมกล่องแสดงผลกว้าง 1280px ที่ความหนาแน่นพิกเซล 2x ซึ่งเป็นกรณีที่พบบ่อยที่สุด ขยับขึ้นเป็น 3840 ถ้าคุณทำ hero เต็มความกว้าง มีฟีเจอร์ซูมสินค้า หรือเป็นแกลเลอรีภาพถ่าย ส่วนการปิดทิ้งทั้งหมดควรทำเฉพาะตอนที่คุณจำเป็นต้องเสิร์ฟไฟล์ต้นฉบับแบบไม่ถูกแตะจริง ๆ