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

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

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

วัดผล

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

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

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

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

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

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

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

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

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

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

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

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

<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>

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

ปิดใช้แคชในเครื่องมือสำหรับนักพัฒนาเว็บใน 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) });
});

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

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

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

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

แผงองค์ประกอบที่มีแท็กดึงข้อมูลล่วงหน้า

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

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

แม้ว่าการดึงข้อมูลล่วงหน้าจะเหมาะกับกรณีการใช้งานนี้มากกว่า แต่ webpack ก็รองรับการโหลดล่วงหน้า ก้อนข้อมูลที่นำเข้าแบบไดนามิกด้วย

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

บทสรุป

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

โดยสรุป

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

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

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