การแยกโค้ดด้วยการนำเข้าแบบไดนามิกใน Next.js

วิธีเพิ่มความเร็วให้แอป Next.js ด้วยกลยุทธ์การแยกโค้ดและการโหลดอัจฉริยะ

สิ่งที่คุณจะได้เรียนรู้

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

การแยกโค้ดตามเส้นทางและตามคอมโพเนนต์

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

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

Next.js รองรับไดนามิก import() ซึ่งจะช่วยให้คุณนำเข้าโมดูล JavaScript (รวมถึงคอมโพเนนต์ React) ได้ แบบไดนามิก และโหลดการนำเข้าแต่ละรายการเป็นกลุ่มแยกกัน ซึ่งจะให้ การแยกโค้ดระดับคอมโพเนนต์และช่วยให้คุณสามารถควบคุมการโหลดทรัพยากร ให้ผู้ใช้ดาวน์โหลดโค้ดที่จำเป็นสำหรับบางส่วนของเว็บไซต์ที่ ที่ผู้ใช้กำลังดูอยู่ ใน Next.js คอมโพเนนต์เหล่านี้จะแสดงผลฝั่งเซิร์ฟเวอร์ (SSR) โดยค่าเริ่มต้น

การทํางานของการนําเข้าแบบไดนามิก

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

ในแอปเวอร์ชันแรก ลูกสุนัขจะอยู่ที่ components/Puppy.js ถึง แสดงลูกสุนัขในหน้าเว็บ แอปนำเข้าคอมโพเนนต์ Puppy ใน index.js ที่มีข้อความนำเข้าแบบคงที่ ให้ทำดังนี้

import Puppy from "../components/Puppy";

หากต้องการดูว่า Next.js รวมแอปเข้าด้วยกันอย่างไร ให้ตรวจสอบการติดตามเครือข่ายในเครื่องมือสำหรับนักพัฒนาเว็บ

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

  2. กด "Control+Shift+J" (หรือ "Command+Option+J" ใน Mac) เพื่อเปิดเครื่องมือสำหรับนักพัฒนาเว็บ

  3. คลิกแท็บเครือข่าย

  4. เลือกช่องทำเครื่องหมายปิดใช้แคช

  5. โหลดหน้าเว็บซ้ำ

เมื่อคุณโหลดหน้าเว็บ โค้ดที่จำเป็นทั้งหมด รวมถึง Puppy.js คอมโพเนนต์ ถูกรวมกลุ่มใน index.js:

แท็บ DevTools Network แสดงไฟล์ JavaScript 6 ไฟล์ ได้แก่ index.js, app.js, webpack.js, main.js, 0.js และไฟล์ dll (dynamic-link library)

เมื่อคุณกดปุ่มคลิกฉัน จะมีเพียงคำขอไฟล์ JPEG ลูกสุนัขเท่านั้น ที่เพิ่มลงในแท็บเครือข่ายแล้ว ให้ทำดังนี้

แท็บเครือข่ายเครื่องมือสำหรับนักพัฒนาเว็บหลังจากคลิกปุ่ม ซึ่งจะแสดงไฟล์ JavaScript 6 รายการและรูปภาพ 1 ภาพ

ข้อเสียของวิธีนี้ก็คือ แม้ว่าผู้ใช้จะไม่คลิกปุ่มเพื่อ เห็นลูกสุนัขจะต้องโหลดคอมโพเนนต์ Puppy เนื่องจากมีองค์ประกอบอยู่ใน index.js ในตัวอย่างเล็กๆ นี้ นั่นไม่ใช่เรื่องใหญ่ แต่เป็นเรื่องของชีวิตจริง แอปพลิเคชันส่วนใหญ่มักมีการปรับปรุงครั้งใหญ่ให้โหลด คอมโพเนนต์ขนาดใหญ่ก็ต่อเมื่อ ตามความจำเป็น

คราวนี้มาดูแอปเวอร์ชันที่ 2 ซึ่งมีการนำเข้าแบบคงที่ แทนที่ด้วยการนำเข้าแบบไดนามิก Next.js มี next/dynamic ซึ่งทำให้ สามารถใช้การนำเข้าแบบไดนามิกสำหรับคอมโพเนนต์ใดๆ ใน "ถัดไป" ได้ดังนี้

import Puppy from "../components/Puppy";
import dynamic from "next/dynamic";

// ...

const Puppy = dynamic(import("../components/Puppy"));

ทำตามขั้นตอนจากตัวอย่างแรกเพื่อตรวจสอบการติดตามเครือข่าย

เมื่อคุณโหลดแอปเป็นครั้งแรก ระบบจะดาวน์โหลดเฉพาะ index.js เท่านั้น เวลานี้ เล็กลง 0.5 KB (ลดลงจาก 37.9 KB เป็น 37.4 KB) เพราะว่า ไม่รวมโค้ดสำหรับคอมโพเนนต์ Puppy:

เครือข่ายเครื่องมือสำหรับนักพัฒนาเว็บแสดงไฟล์ JavaScript 6 ไฟล์เดียวกัน ยกเว้นดัชนี.js ซึ่งมีขนาดเล็กกว่า 0.5 KB

ตอนนี้คอมโพเนนต์ Puppy ได้รวมอยู่ในกลุ่มแยกต่างหาก ซึ่งก็คือ 1.js แล้ว ซึ่งจะโหลดขึ้นมาเท่านั้น เมื่อคุณกดปุ่ม

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

ในการใช้งานจริง คอมโพเนนต์มักมาก ใหญ่ขึ้น และการโหลดแบบ Lazy Loading สามารถตัดเพย์โหลด JavaScript เริ่มต้นได้หลายร้อยกิโลไบต์

การนําเข้าแบบไดนามิกที่มีสัญญาณบอกสถานะการโหลดที่กําหนดเอง

เมื่อโหลดทรัพยากรแบบ Lazy Loading คุณควรใส่สัญญาณบอกสถานะการโหลดด้วย ในกรณีที่เกิดความล่าช้า ใน Next.js คุณสามารถทำได้โดยการระบุ อาร์กิวเมนต์เพิ่มเติมไปยังฟังก์ชัน dynamic():

const Puppy = dynamic(() => import("../components/Puppy"), {
  loading: () => <p>Loading...</p>
});

หากต้องการดูการทำงานของตัวบอกการโหลด ให้จำลองการเชื่อมต่อเครือข่ายที่ช้าใน เครื่องมือสำหรับนักพัฒนาเว็บ:

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

  2. กด "Control+Shift+J" (หรือ "Command+Option+J" ใน Mac) เพื่อเปิดเครื่องมือสำหรับนักพัฒนาเว็บ

  3. คลิกแท็บเครือข่าย

  4. เลือกช่องทำเครื่องหมายปิดใช้แคช

  5. ในรายการแบบเลื่อนลงการควบคุม ให้เลือก 3G ที่รวดเร็ว

  6. กดปุ่มคลิกฉัน

ตอนนี้เมื่อคุณคลิกปุ่ม จะใช้เวลาสักครู่ในการโหลดคอมโพเนนต์และแอป จะแสดงปุ่ม "กำลังโหลด..." ในระหว่างนี้

หน้าจอมืดพร้อมข้อความ

การนำเข้าแบบไดนามิกที่ไม่มี SSR

หากต้องการแสดงผลคอมโพเนนต์เฉพาะบนฝั่งไคลเอ็นต์ (เช่น แชท ใหม่) ก็ทำได้โดยตั้งค่าตัวเลือก ssr เป็น false

const Puppy = dynamic(() => import("../components/Puppy"), {
  ssr: false,
});

บทสรุป

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