Preload, prefetch และ preconnect: เมื่อใดที่แต่ละอย่างช่วยได้จริง
Resource hints มีประโยชน์เมื่อสอดคล้องกับคอขวดจริงของเบราว์เซอร์ หากใช้แบบสุ่มสี่สุ่มห้า จะเพิ่มสัญญาณรบกวนด้านลำดับความสำคัญ และบางครั้งทำให้หน้าเว็บช้าลง
สารบัญ
- Resource hints ไม่ใช่เวทมนตร์
- สิ่งที่เบราว์เซอร์ทำได้ดีอยู่แล้ว
- Preload: สำหรับ resources ของหน้าปัจจุบันที่ถูกค้นพบช้าเกินไป
- Preload และ LCP images
- Prefetch: สำหรับหน้าถัดไป ไม่ใช่หน้านี้
- Preconnect: สำหรับ connections ที่มีต้นทุนสูงไปยัง origins สำคัญ
- DNS-prefetch: ญาติที่เบากว่า
- วิธีตัดสินใจ: workflow เชิงปฏิบัติ
- 1. ระบุคอขวด
- 2. เพิ่ม hint ทีละรายการ
- 3. ตรวจสอบผลข้างเคียงด้าน priority
- 4. ตรวจสอบ headers และ caching
- ข้อผิดพลาดที่พบบ่อย
- Preloading มากเกินไป
- ใช้ prefetch กับ resources ที่จำเป็น
- Preconnecting ไปยัง third party ทุกแห่ง
- ลืมเงื่อนไขบน mobile
- ตารางตัดสินใจแบบง่าย
- กฎแบบสงบ
Resource hints ไม่ใช่เวทมนตร์
preload, prefetch, และ preconnect มักถูกมองเป็น checklist ด้านประสิทธิภาพ ใส่ tag สักสองสามตัวใน <head> รัน Lighthouse อีกครั้ง แล้วรู้สึกดีขึ้น แต่นั่นไม่ใช่วิธีที่มันทำงาน
Hints เหล่านี้คือคำสั่งให้กับ loading pipeline ของเบราว์เซอร์ มันช่วยได้เมื่อคุณรู้บางอย่างที่เบราว์เซอร์ไม่สามารถค้นพบได้เร็วพอ และอาจส่งผลเสียเมื่อคุณคาดเดา จัดลำดับความสำคัญให้กับงานที่ไม่สำคัญมากเกินไป หรืออุ่นเครื่อง connection ที่ผู้ใช้ไม่เคยต้องใช้
สรุปสั้น ๆ:
- ใช้
preloadสำหรับ resources ที่จำเป็นต่อหน้าปัจจุบัน แต่ถูกค้นพบช้าเกินไป - ใช้
prefetchสำหรับ resources ของการนำทางในอนาคตที่มีแนวโน้มจะเกิดขึ้น ไม่ใช่สิ่งจำเป็นของหน้าปัจจุบัน - ใช้
preconnectสำหรับ origins สำคัญของ third-party ที่การตั้งค่า connection เป็นความล่าช้าจริง
คำถามเชิงปฏิบัติไม่ใช่ “hint ไหนเร็วที่สุด?” แต่คือ “เบราว์เซอร์กำลังรออะไรอยู่ และ hint นี้ช่วยตัดการรอนั้นได้หรือไม่?”
สิ่งที่เบราว์เซอร์ทำได้ดีอยู่แล้ว
เบราว์เซอร์สมัยใหม่ไม่ใช่เพียงตัวดาวน์โหลดไฟล์แบบ passive มัน parse HTML, scan ล่วงหน้าเพื่อหา resources, กำหนด priorities, reuse connections, delay งานที่ยังไม่มองเห็น และปรับตัวตามสภาพเครือข่าย
นั่นหมายความว่า resource hints ควรถูกใช้อย่างเลือกสรร หาก stylesheet, script, image หรือ font ถูกค้นพบเร็วอยู่แล้วและได้รับ priority ที่เหมาะสม การเพิ่ม hint อาจไม่ช่วยอะไรเลย แย่กว่านั้น มันอาจไปแข่งขันกับ resources ที่สำคัญกว่า
ก่อนเพิ่ม hints ให้ดู waterfall trace ใน DevTools หรือ lab report หากคุณใช้ Lighthouse ให้เริ่มจาก diagnostics แทนที่จะดู score; เรามีคู่มือแยกเกี่ยวกับการอ่าน Lighthouse report โดยไม่ตื่นตระหนก — แต่โปรดทราบว่า URL ที่ถูกต้องคำนึงถึงตัวพิมพ์เล็ก-ใหญ่ ดังนั้นให้ใช้บทความที่ลิงก์จาก navigation ของไซต์คุณหากจำเป็น
หลักฐานจริงมักเห็นได้ในสามจุด:
- Resource สำคัญเริ่มช้าเพราะเบราว์เซอร์ค้นพบมันช้า
- Connection ไปยัง origin สำคัญใช้เวลาชัดเจนก่อน request แรก
- Resource ของหน้าถัดไปคาดการณ์ได้สูงและมีต้นทุนต่ำพอที่จะ fetch ในช่วง idle
หากไม่มีข้อใดเป็นจริง hint ก็น่าจะเป็นเพียงของตกแต่ง
Preload: สำหรับ resources ของหน้าปัจจุบันที่ถูกค้นพบช้าเกินไป
preload บอกเบราว์เซอร์ว่า: “Fetch resource นี้ตอนนี้ เพราะหน้าปัจจุบันจะต้องใช้มัน”
ตัวอย่างทั่วไปคือ web font ที่ถูกอ้างอิงอยู่ใน CSS เบราว์เซอร์ต้องดาวน์โหลด HTML, ค้นพบ CSS, ดาวน์โหลด CSS, parse มัน, ค้นพบ font แล้วจึง request font หาก font นั้นสำคัญต่อข้อความ above-the-fold การค้นพบอาจช้าพอที่จะทำให้เกิด layout shifts หรือทำให้การแสดงข้อความล่าช้า
Preload สามารถย้าย request นั้นให้เกิดเร็วขึ้น:
<link rel='preload' href='/fonts/inter-var.woff2' as='font' type='font/woff2' crossorigin>
Attribute as สำคัญ มันบอกเบราว์เซอร์ว่า resource นี้เป็นประเภทใด ซึ่งส่งผลต่อ priority, caching, content security policy และ request headers โดยปกติ fonts ยังต้องใช้ crossorigin แม้จะเสิร์ฟจากไซต์เดียวกัน เพราะการ fetch font ใช้ CORS mode
ผู้สมัครที่ดีสำหรับ preload ได้แก่:
- Web font หลักที่ใช้กับข้อความที่มองเห็นได้
- Hero image ที่เป็นองค์ประกอบ Largest Contentful Paint และไม่ถูกค้นพบเร็ว
- ไฟล์ CSS สำคัญที่ถูกโหลดทางอ้อม
- Module หรือ script ที่ต้องใช้เร็วมาก แต่ถูกซ่อนไว้หลัง script อื่น
ผู้สมัครที่ไม่ดีสำหรับ preload ได้แก่:
- Font weight ทุกแบบใน design system
- Images below the fold
- Scripts ที่ไม่จำเป็นต่อการ render ขั้นต้น
- Resources ที่เบราว์เซอร์ค้นพบอยู่แล้วใน HTML chunk แรก
Preload ทรงพลังเพราะมันส่งผลต่อ priority ของหน้าปัจจุบัน และนั่นก็เป็นเหตุผลที่มันถูกใช้ผิดได้ง่ายเช่นกัน หากคุณ preload assets ขนาดใหญ่ห้ารายการ คุณไม่ได้ช่วยเบราว์เซอร์อีกต่อไป คุณกำลังโต้แย้งกับมัน
Fonts เป็นกรณีคลาสสิก การ preload ไฟล์ font หลักหนึ่งไฟล์อาจช่วยได้ การ preload หก weights รวมถึง italics มักทำให้แย่ลง หาก fonts คือคอขวดของคุณ ให้แก้ชุด font ก่อน; คู่มือของเราเกี่ยวกับเหตุผลที่ web fonts ยังคงเป็นชัยชนะด้านประสิทธิภาพที่ง่ายที่สุดในเว็บไซต์ส่วนใหญ่ อธิบายการ cleanup นี้ละเอียดขึ้น
Preload และ LCP images
การ preload LCP image อาจมีประโยชน์เมื่อ image ไม่ปรากฏใน HTML เริ่มต้น สาเหตุทั่วไปได้แก่ CSS background images, components ที่ render ฝั่ง client หรือ responsive image logic ที่ปรากฏช้า
แต่หาก hero image ของคุณอยู่ใน HTML อยู่แล้วในรูป <img> พร้อม srcset, sizes, dimensions ที่เหมาะสม และไม่มี lazy loading เบราว์เซอร์ก็น่าจะพบมันได้เร็ว ในกรณีนั้น การเพิ่ม fetchpriority='high' อาจเหมาะกว่า preload ขึ้นอยู่กับหน้า
การทดสอบที่ดี: หาก image request เริ่มช้าใน waterfall และกลายเป็นองค์ประกอบ LCP ให้พิจารณา preload หากมันเริ่มเร็วแต่ดาวน์โหลดช้า ปัญหาคือขนาด, format, พฤติกรรมของ CDN หรือ server latency — ไม่ใช่การค้นพบ สำหรับการตัดสินใจเรื่อง image format โปรดดู เมื่อใดที่ AVIF ชนะ WebP และเมื่อใดที่ไม่ใช่
Prefetch: สำหรับหน้าถัดไป ไม่ใช่หน้านี้
prefetch บอกเบราว์เซอร์ว่า: “Resource นี้อาจจำเป็นในไม่ช้า แต่ไม่จำเป็นตอนนี้”
ความแตกต่างนี้สำคัญ Prefetch ถูกตั้งใจให้มี priority ต่ำ เบราว์เซอร์อาจ fetch มันระหว่างช่วง idle และเก็บไว้ใช้ภายหลัง มันอาจข้ามไปเลยบน connection ที่แย่, data-saving modes หรือเมื่อมี memory pressure
ใช้ prefetch เมื่อเจตนาของผู้ใช้ชัดเจนพอที่จะทำให้ resource ถัดไปมีแนวโน้มจะถูกใช้
ผู้สมัครที่ดีสำหรับ prefetch ได้แก่:
- ขั้นตอนถัดไปใน checkout หลายหน้า
- Search results หลังจากผู้ใช้เริ่มพิมพ์ query หาก route ถัดไปคาดการณ์ได้
- Documentation pages ที่ลิงก์จาก table of contents เมื่อผู้ใช้กำลังอ่านเนื้อหาใกล้เคียงอย่าง active
- Route chunks ใน single-page app หลังจากผู้ใช้ hover หรือ focus navigation item
ผู้สมัครที่ไม่ดีสำหรับ prefetch ได้แก่:
- Navigation tree ทั้งหมดของคุณ
- Videos หรือ image galleries ขนาดใหญ่
- Third-party scripts “เผื่อไว้”
- Pages ที่ผู้ใช้แทบไม่ไปต่อเป็นหน้าถัดไป
Prefetch เป็นจุดที่ความยับยั้งชั่งใจให้ผลตอบแทน Resource ที่ fetch มาแล้วไม่ได้ใช้ไม่ใช่ของฟรี มันใช้ bandwidth, server capacity, energy และอาจรวมถึง data ของผู้ใช้ บน mobile networks การ fetch แบบคาดการณ์อาจไม่เป็นมิตรอย่างจริงจัง
สำหรับหลายไซต์ กลยุทธ์ prefetch ที่ดีที่สุดคืออิงตาม intent อย่า prefetch หน้า pricing ทันทีที่ home page โหลด ให้ prefetch เมื่อผู้ใช้เปิด pricing menu, hover ลิงก์ pricing หรือ scroll ใกล้ call-to-action ที่คาดการณ์การนำทางได้ชัดเจน
อย่าลืมด้วยว่าพฤติกรรมของเบราว์เซอร์แตกต่างกัน บางเบราว์เซอร์ระมัดระวังกับ prefetch; privacy settings บางอย่างลดหรือปิด speculative loading ให้มอง prefetch เป็นการปรับปรุงแบบ opportunistic ไม่ใช่กลไกเพื่อความถูกต้อง
Preconnect: สำหรับ connections ที่มีต้นทุนสูงไปยัง origins สำคัญ
preconnect บอกเบราว์เซอร์ว่า: “เริ่มตั้งค่า connection ไปยัง origin นี้ตอนนี้”
นั่นอาจรวมถึง DNS lookup, TCP connection และ TLS negotiation สำหรับ third-party origins การตั้งค่านี้อาจใช้เวลาหลายร้อย milliseconds โดยเฉพาะบนเครือข่าย latency สูง หากหน้าเว็บต้องใช้ request สำคัญจาก origin นั้นในไม่ช้า preconnect สามารถทำให้ request ภายหลังเร็วขึ้น
ตัวอย่าง:
<link rel='preconnect' href='https://fonts.gstatic.com' crossorigin>
ผู้สมัครที่ดีสำหรับ preconnect ได้แก่:
- Font origin ที่ใช้กับข้อความแบบ render-blocking
- API origin สำคัญที่จำเป็นระหว่างการโต้ตอบแรกเริ่ม
- CDN origin ที่เสิร์ฟ assets above-the-fold
- Payments หรือ identity provider ที่จำเป็นทันทีหลังการกระทำของผู้ใช้
ผู้สมัครที่ไม่ดีสำหรับ preconnect ได้แก่:
- Analytics และ advertising endpoints ที่ไม่สำคัญต่อผู้ใช้
- Origins ที่ใช้เฉพาะบาง sessions
- รายการ third parties ยาว ๆ
- Same-origin resources ซึ่งเบราว์เซอร์มี connection อยู่แล้วหรือจะเปิดในไม่ช้า
Preconnect มีต้นทุนในการคงไว้ Open sockets ใช้ memory และ network resources เบราว์เซอร์จะปิด unused connections แต่ก็ไม่ได้ทำให้ preconnect ที่ไม่จำเป็นกลายเป็นสิ่งไม่มีอันตราย
กฎที่มีประโยชน์: preconnect กับ third-party origins ที่มั่นใจสูงไม่เกินหนึ่งหรือสองรายการต่อหน้า หากคุณรู้สึกอยากเพิ่มมากกว่านั้น third-party architecture ของคุณน่าจะต้องได้รับการทบทวนมากกว่าที่ hints ของคุณต้องขยาย
DNS-prefetch: ญาติที่เบากว่า
คุณอาจเห็น dns-prefetch ด้วย:
<link rel='dns-prefetch' href='https://example-cdn.com'>
สิ่งนี้ resolve เฉพาะ domain name มันไม่เปิด TCP หรือ TLS connection มีต้นทุนต่ำกว่า preconnect แต่ก็ช่วยได้น้อยกว่าเช่นกัน
DNS-prefetch อาจสมเหตุสมผลสำหรับ third-party origins ที่มีความมั่นใจต่ำกว่า ซึ่ง full preconnect ดู aggressive เกินไป ในทางปฏิบัติ หาก origin สำคัญและจะถูกใช้ในไม่ช้าอย่างแน่นอน ให้เลือก preconnect หากเป็นเพียงความเป็นไปได้ ให้ใช้ DNS-prefetch หรือไม่ต้องทำอะไรเลย
วิธีตัดสินใจ: workflow เชิงปฏิบัติ
เริ่มจากการวัดผล ไม่ใช่ tags
1. ระบุคอขวด
เปิด performance trace และมองหา late discovery Font, hero image หรือ script request เริ่มหลังจากมีการดาวน์โหลดและ parse ไฟล์อื่นแล้วเท่านั้นหรือไม่ หากใช่ นั่นคือผู้สมัครสำหรับ preload
หาก request เริ่มหลังจากการตั้งค่า DNS/TCP/TLS ที่ยาวไปยัง third-party origin เท่านั้น นั่นคือผู้สมัครสำหรับ preconnect
หากหน้าปัจจุบันดีอยู่แล้ว แต่การนำทางถัดไปช้าอย่างคาดการณ์ได้ prefetch อาจช่วยได้
2. เพิ่ม hint ทีละรายการ
Resource hints มีปฏิสัมพันธ์กัน เพิ่มทีละรายการ ทดสอบ และเก็บไว้เฉพาะเมื่อ waterfall ดีขึ้นและ metrics ที่ผู้ใช้รับรู้ไม่ถดถอย
สำหรับ preload ให้ดูว่า resource ที่ใส่ hint ถูกใช้จริงในไม่ช้าหรือไม่ Chrome อาจเตือนเมื่อ resource ที่ถูก preload ไม่ถูกใช้หลัง load ไม่นาน ให้ถือคำเตือนนั้นอย่างจริงจัง
3. ตรวจสอบผลข้างเคียงด้าน priority
Preload อาจดึง bandwidth ออกจาก CSS, JavaScript หรือ images ที่สำคัญกว่า Preconnect อาจครอบครอง connection slot Prefetch อาจเพิ่ม background traffic
ผลลัพธ์ที่ถูกต้องไม่ใช่ “ไฟล์ที่ใส่ hint เริ่มเร็วขึ้น” ผลลัพธ์ที่ถูกต้องคือ “หน้าเว็บดีขึ้นอย่างมีความหมายสำหรับผู้ใช้” ดู LCP, INP, CLS และ real-user monitoring เมื่อทำได้
4. ตรวจสอบ headers และ caching
Hints สามารถส่งใน HTML หรือ HTTP Link headers ได้ Headers มีประโยชน์เมื่อ server รู้ตั้งแต่ต้นว่าหน้าจะต้องใช้อะไร แต่ตรวจสอบแบบคร่าว ๆ ได้ยากกว่า หากคุณกำลัง debug ว่า hint มีอยู่จริงใน production หรือไม่ raw headers สำคัญ; นี่เป็นสถานการณ์แบบเดียวกับที่ครอบคลุมใน คู่มือของเราเกี่ยวกับการ debug redirects และ HTTP headers
Caching ก็สำคัญเช่นกัน การ preload resource ด้วย credentials ที่ไม่ตรงกัน, as ผิด หรือ URL parameters ต่างกัน อาจทำให้เกิดการดาวน์โหลดซ้ำ นั่นเป็นหนึ่งในวิธีที่พบได้บ่อยที่สุดที่ preload ซึ่งตั้งใจดีจะกลายเป็น performance bug
ข้อผิดพลาดที่พบบ่อย
Preloading มากเกินไป
ถ้าทุกอย่างสำคัญ ก็ไม่มีอะไรสำคัญ จำกัด preload ไว้ที่ resources ที่จำเป็นต่อ initial rendering หรือ immediate interactivity หน้าเว็บทั่วไปควรมี preloads ศูนย์ถึงสามรายการ ไม่ใช่ยี่สิบ
ใช้ prefetch กับ resources ที่จำเป็น
Prefetch มี priority ต่ำและเป็น optional อย่าใช้กับ assets ที่หน้าปัจจุบันจำเป็นต้องใช้ หากหน้าต้องใช้ตอนนี้ ให้พิจารณา preload หรือการค้นพบผ่าน HTML ตามปกติ
Preconnecting ไปยัง third party ทุกแห่ง
หน้าที่มี third-party จำนวนมากมักมี external origins สิบรายการหรือมากกว่า การ preconnect ไปทั้งหมดสร้างสัญญาณรบกวน เลือกหนึ่งหรือสองรายการที่ทั้งสำคัญและถูกใช้อย่างคาดการณ์ได้
ลืมเงื่อนไขบน mobile
Resource hints มีค่ามากที่สุดบน connections ที่ช้ากว่า แต่ก็อันตรายที่สุดที่นั่นเช่นกัน Prefetch ที่สูญเปล่าบน desktop connection ที่เร็วเป็นเพียงความคลาดเคลื่อนเล็กน้อย แต่บน mobile plan ที่จำกัด มันเป็นการแลกเปลี่ยนที่ไม่ดี
ตารางตัดสินใจแบบง่าย
| Situation | Best hint | Why | |---|---:|---| | Critical font ที่ค้นพบผ่าน CSS | preload | หน้าปัจจุบันต้องใช้ และการค้นพบเกิดช้า | | Hero image ที่ซ่อนอยู่หลัง CSS หรือ client rendering | preload | อาจปรับปรุง LCP หาก image เริ่มช้า | | Route ถัดไปที่มีแนวโน้มหลัง user intent | prefetch | ช่วยการนำทางในอนาคตโดยไม่ block หน้าปัจจุบัน | | Third-party font/API origin สำคัญ | preconnect | เอาการตั้งค่า connection ออกจาก critical path | | Third-party origin ที่เป็นไปได้แต่ไม่แน่นอน | dns-prefetch หรือไม่ใช้ | ต้นทุนต่ำกว่า ความมั่นใจต่ำกว่า | | Image below-the-fold | none | ปล่อยให้ lazy loading และ browser priority ทำงาน |
กฎแบบสงบ
Resource hints ทำงานได้ดีที่สุดเมื่อมันธรรมดาและเฉพาะเจาะจง หนึ่ง font หนึ่ง LCP image หนึ่ง third-party origin สำคัญ หนึ่ง route ถัดไปที่มีแนวโน้มหลัง intent
มันทำงานได้แย่เมื่อใช้ด้วยความคาดหวังแบบลอย ๆ: บางทีผู้ใช้อาจต้องใช้สิ่งนี้ บางทีเบราว์เซอร์ควร fetch สิ่งนั้น บางที hints ที่มากขึ้นหมายถึงความเร็วที่มากขึ้น
เบราว์เซอร์ optimize อย่างจริงจังอยู่แล้ว งานของคุณไม่ใช่การ micromanage ทุก request งานของคุณคือแก้ไขไม่กี่กรณีที่เบราว์เซอร์ขาดข้อมูลในช่วงเวลาที่เหมาะสม