ลดเพย์โหลด JavaScript ด้วยการแยกโค้ด

ไม่มีใครชอบการรอคอย ผู้ใช้กว่า 50% ออกจากเว็บไซต์หากใช้เวลาโหลดนานกว่า 3 วินาที

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

เหตุใดการแยกโค้ดจึงมีประโยชน์

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

เมื่อพูดถึง Core Web Vitals การลดเพย์โหลด JavaScript ที่ดาวน์โหลดเมื่อเริ่มต้นใช้งานจะช่วยให้เวลาในการโต้ตอบกับ Next Paint (INP) ดีขึ้น เหตุผลที่อยู่เบื้องหลังคือ เมื่อทำให้เทรดหลักว่างมากขึ้น แอปพลิเคชันจะตอบสนองต่อข้อมูลจากผู้ใช้ได้เร็วขึ้นโดยลดค่าใช้จ่ายในการเริ่มต้นเกี่ยวกับการแยกวิเคราะห์ คอมไพล์ และการดำเนินการเกี่ยวกับ JavaScript

การลดขนาดของเพย์โหลด JavaScript ที่รับผิดชอบในการแสดงผลมาร์กอัปอาจนำไปสู่เวลา Largest Contentful Paint (LCP) ที่ดีขึ้น ทั้งนี้ขึ้นอยู่กับสถาปัตยกรรมของเว็บไซต์ โดยเฉพาะอย่างยิ่งหากเว็บไซต์อาศัยการแสดงผลฝั่งไคลเอ็นต์อย่างมาก กรณีนี้อาจเกิดขึ้นเมื่อเบราว์เซอร์ค้นพบทรัพยากร LCP ล่าช้า จนกว่ามาร์กอัปฝั่งไคลเอ็นต์จะเสร็จสมบูรณ์ หรือเมื่อเทรดหลักไม่ว่างเกินกว่าที่จะแสดงผลองค์ประกอบ LCP ดังกล่าว ทั้ง 2 สถานการณ์อาจทำให้เวลา LCP ของหน้าเว็บล่าช้าได้

วัดระยะทาง

Lighthouse แสดงการตรวจสอบที่ล้มเหลวเมื่อใช้เวลานานมากในการ เรียกใช้ JavaScript ทั้งหมดในหน้าเว็บ

การตรวจสอบ Lighthouse ที่ไม่สำเร็จซึ่งแสดงสคริปต์ที่ใช้เวลาดำเนินการนานเกินไป

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

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

import moduleA from "library";

form.addEventListener("submit", e => {
  e.preventDefault();
  someFunction();
});

const someFunction = () => {
  // uses moduleA
}

ในส่วนนี้ someFunction ใช้โมดูลที่นำเข้าจากไลบรารีที่เฉพาะเจาะจง ถ้า โมดูลนี้ไม่ได้ถูกใช้ที่อื่น โค้ดบล็อกจึงสามารถแก้ไขให้ใช้ การนําเข้าแบบไดนามิกเพื่อดึงข้อมูลเฉพาะเมื่อผู้ใช้ส่งแบบฟอร์มเท่านั้น

form.addEventListener("submit", e => {
  e.preventDefault();
  import('library.moduleA')
    .then(module => module.default) // using the default export
    .then(() => someFunction())
    .catch(handleError());
});

const someFunction = () => {
    // uses moduleA
}

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

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

การแยกในระดับเส้นทางหรือคอมโพเนนต์เมื่อใช้เฟรมเวิร์กฝั่งไคลเอ็นต์ วิธีที่ง่ายขึ้นในการโหลดส่วนต่างๆ ของแอปพลิเคชันแบบ Lazy Loading หลายหน้า เฟรมเวิร์กยอดนิยมที่ใช้ Webpack ก็มีองค์ประกอบเพื่อทำการโหลดแบบ Lazy Loading ได้ง่ายกว่าการไปกำหนดค่าด้วยตัวเอง