Codelab: โหลดเนื้อหาที่สำคัญไว้ล่วงหน้าเพื่อปรับปรุงความเร็วในการโหลด

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

ภาพหน้าจอแอป

วัดระยะทาง

ก่อนอื่นให้วัดประสิทธิภาพของเว็บไซต์ก่อนที่จะเพิ่มการเพิ่มประสิทธิภาพ

  • หากต้องการดูตัวอย่างเว็บไซต์ ให้กดดูแอป แล้วกดเต็มหน้าจอ เต็มหน้าจอ

เรียกใช้การตรวจสอบประสิทธิภาพของ Lighthouse (Lighthouse > ตัวเลือก > ประสิทธิภาพ) ใน Glitch เวอร์ชันที่เผยแพร่ (ดูค้นพบโอกาสในการปรับปรุงประสิทธิภาพด้วย Lighthouse ด้วย)

Lighthouse แสดงการตรวจสอบที่ไม่สําเร็จต่อไปนี้สําหรับทรัพยากรที่ดึงข้อมูลล่าช้า

Lighthouse: การตรวจสอบการโหลดคีย์คำขอล่วงหน้า
  • กดแป้น Control+Shift+J (หรือ Command+Option+J ใน Mac) เพื่อเปิดเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์
  • คลิกแท็บเครือข่าย
แผงเครือข่ายที่มีทรัพยากรที่ค้นพบล่าสุด

ไฟล์ main.css ไม่ได้ดึงข้อมูลโดยองค์ประกอบลิงก์ (<link>) ที่วางไว้ในเอกสาร HTML แต่ไฟล์ JavaScript แยกต่างหากชื่อ fetch-css.js จะแนบองค์ประกอบลิงก์กับ DOM หลังจากเหตุการณ์ window.onLoad ซึ่งหมายความว่าระบบจะดึงข้อมูลไฟล์หลังจากเบราว์เซอร์แยกวิเคราะห์และดำเนินการกับไฟล์ JS เสร็จแล้วเท่านั้น ในทํานองเดียวกัน ระบบจะดึงข้อมูลแบบอักษรเว็บ (K2D.woff2) ที่ระบุภายใน main.css ก็ต่อเมื่อไฟล์ CSS ดาวน์โหลดเสร็จแล้วเท่านั้น

ห่วงโซ่คำขอที่สำคัญแสดงลำดับทรัพยากรที่เบราว์เซอร์จัดลําดับความสําคัญและดึงข้อมูล หน้าเว็บนี้มีลักษณะดังนี้

├─┬ / (initial HTML file)
  └── fetch-css.js
    └── main.css
      └── K2D.woff2

เนื่องจากไฟล์ CSS อยู่ในระดับที่ 3 ของเชนคำขอ Lighthouse จึงระบุว่าเป็นทรัพยากรที่ค้นพบช้า

โหลดทรัพยากรสําคัญล่วงหน้า

ไฟล์ main.css เป็นชิ้นงานสําคัญที่จําเป็นทันทีที่โหลดหน้าเว็บ สําหรับไฟล์สําคัญ เช่น ทรัพยากรนี้ที่ดึงข้อมูลในภายหลังในแอปพลิเคชัน ให้ใช้แท็กการโหลดลิงก์ล่วงหน้าเพื่อแจ้งให้เบราว์เซอร์ดาวน์โหลดไฟล์เร็วขึ้นด้วยการเพิ่มองค์ประกอบ Link ไว้ที่ส่วนหัวของเอกสาร

เพิ่มแท็กการโหลดล่วงหน้าสําหรับแอปพลิเคชันนี้

<head>
  <!-- ... -->
  <link rel="preload" href="main.css" as="style">
</head>

แอตทริบิวต์ as ใช้เพื่อระบุประเภททรัพยากรที่ดึงข้อมูล และ as="style" ใช้เพื่อโหลดไฟล์สไตล์ชีตล่วงหน้า

โหลดแอปพลิเคชันซ้ำและดูที่แผงเครือข่ายในเครื่องมือสำหรับนักพัฒนาเว็บ

แผงเครือข่ายที่มีทรัพยากรที่โหลดไว้ล่วงหน้า

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

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

<head>
  <!-- ... -->
  <link rel="preload" href="main.css" as="style">
  <link rel="preload" href="details.css" as="style">
</head>

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

แผงเครือข่ายที่มีการโหลดล่วงหน้าที่ไม่จำเป็น

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

คำเตือนการโหลดล่วงหน้าในคอนโซล

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

<head>
  <!-- ... -->
  <link rel="preload" href="main.css" as="style">
  <link rel="preload" href="details.css" as="style">
</head>

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

โหลดทรัพยากรในอนาคตล่วงหน้า

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

ในเว็บไซต์นี้ การคลิกรูปภาพจะนำคุณไปยังdetails/ เส้นทางแยกต่างหาก

รายละเอียดเส้นทาง

ไฟล์ CSS แยกต่างหากชื่อ details.css มีสไตล์ทั้งหมดที่จําเป็นสําหรับหน้าเว็บที่เรียบง่ายนี้ เพิ่มองค์ประกอบลิงก์ลงใน index.html เพื่อเตรียมทรัพยากรนี้ล่วงหน้า

<head>
  <!-- ... -->
  <link rel="prefetch" href="details.css">
</head>

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

ปิดใช้แคชในเครื่องมือสำหรับนักพัฒนาเว็บใน Chrome

โหลดแอปพลิเคชันอีกครั้งและสังเกตว่ามีการส่งคำขอที่มีลำดับความสำคัญต่ำมากสำหรับ details.css อย่างไรหลังจากที่ดึงข้อมูลไฟล์อื่นๆ ทั้งหมดแล้ว

แผงเครือข่ายที่มีทรัพยากรที่ดึงข้อมูลไว้ล่วงหน้า

เมื่อเครื่องมือสำหรับนักพัฒนาเว็บเปิดอยู่ ให้คลิกรูปภาพในเว็บไซต์เพื่อไปยังหน้า details เนื่องจากมีการใช้องค์ประกอบลิงก์ใน details.html เพื่อดึงข้อมูล details.css ระบบจึงส่งคําขอทรัพยากรตามที่คาดไว้

คำขอเครือข่ายในหน้ารายละเอียด

คลิกคำขอเครือข่าย details.css ในเครื่องมือสำหรับนักพัฒนาเว็บเพื่อดูรายละเอียด คุณจะเห็นระบบดึงข้อมูลไฟล์จากแคชดิสก์ของเบราว์เซอร์

คำขอรายละเอียดที่ดึงมาจากแคชของดิสก์

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

การโหลดล่วงหน้าและการดึงข้อมูลล่วงหน้าด้วย webpack

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

แอป Magic Sorter ที่แสดงการแยกโค้ด

คุณสามารถเข้าถึงข้อบกพร่องของแอปพลิเคชันนี้ได้ที่นี่

บล็อกโค้ดต่อไปนี้ที่อยู่ใน src/index.js, มีหน้าที่ในการนําเข้าเมธอดแบบไดนามิกเมื่อมีการคลิกปุ่ม

form.addEventListener("submit", e => {
  e.preventDefault()
  import('lodash.sortby')
    .then(module => module.default)
    .then(sortInput())
    .catch(err => { alert(err) });
});

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

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

form.addEventListener("submit", e => {
  e.preventDefault()
  import(/* webpackPrefetch: true */ 'lodash.sortby')
    .then(module => module.default)
    .then(sortInput())
    .catch(err => { alert(err) });
});

เมื่อโหลดแอปพลิเคชันอีกครั้ง webpack จะแทรกแท็ก prefetch สําหรับทรัพยากรลงในส่วนหัวของเอกสาร ซึ่งจะแสดงในแผงองค์ประกอบในเครื่องมือสําหรับนักพัฒนาเว็บ

แผงองค์ประกอบที่มีแท็ก prefetch

การสังเกตคําขอในแผงเครือข่ายยังแสดงให้เห็นด้วยว่ามีการดึงข้อมูลกลุ่มนี้โดยมีลําดับความสําคัญต่ำหลังจากที่มีการขอทรัพยากรอื่นๆ ทั้งหมดแล้ว

แผงเครือข่ายที่มีคำขอที่ดึงข้อมูลล่วงหน้า

แม้ว่าการโหลดล่วงหน้าจะเหมาะสมกับกรณีการใช้งานนี้มากกว่า แต่ Webpack ยังรองรับการโหลดล่วงหน้าของกลุ่มที่นําเข้าแบบไดนามิกด้วย

import(/* webpackPreload: true */ 'module')

บทสรุป

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

โดยสรุป

  • ใช้การโหลดล่วงหน้าสำหรับทรัพยากรที่ค้นพบช้า แต่มีความสำคัญต่อหน้าปัจจุบัน
  • ใช้การดึงข้อมูลล่วงหน้าสำหรับทรัพยากรที่จําเป็นสําหรับเส้นทางการนําทางหรือการดำเนินการของผู้ใช้ในอนาคต

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

หากต้องการข้อมูลเพิ่มเติมเกี่ยวกับแง่มุมที่เฉพาะเจาะจงของผลกระทบที่การโหลดล่วงหน้าและการโหลดล่วงหน้ามีต่อหน้าเว็บ โปรดอ่านบทความต่อไปนี้