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

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

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

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

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

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

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

วัดผล

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

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

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

Module Bundler ที่ได้รับความนิยม เช่น webpack Parcel และ Rollup ช่วยให้คุณแยก Bundle ได้โดยใช้การนำเข้าแบบไดนามิก ตัวอย่างเช่น ดูข้อมูลโค้ดต่อไปนี้ซึ่งแสดงตัวอย่างของ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 หรือแสดงต่อผู้ใช้เฉพาะเมื่อจำเป็นหลังจาก ส่งแบบฟอร์มแล้วเท่านั้น หากต้องการปรับปรุงประสิทธิภาพของหน้าเว็บเพิ่มเติม ให้โหลดชิ้นส่วนที่สำคัญล่วงหน้าเพื่อจัดลําดับความสําคัญและดึงข้อมูลให้เร็วขึ้น

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

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