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

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

เผยแพร่: 8 พฤศจิกายน 2019

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

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

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

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

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

การนำเข้าแบบไดนามิกในการทำงาน

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

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

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

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

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

  2. กด `Control+Shift+J` (หรือ `Command+Option+J` ใน Mac) เพื่อเปิด DevTools

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

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

  5. โหลดหน้าซ้ำ

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

แท็บเครือข่ายของ DevTools แสดงไฟล์ JavaScript 6 ไฟล์ ได้แก่ index.js, app.js, webpack.js, main.js, 0.js และไฟล์ dll (ไลบรารีลิงก์แบบไดนามิก)

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

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

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

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

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

เครือข่าย DevTools แสดงไฟล์ JavaScript 6 ไฟล์เดียวกัน ยกเว้น index.js ที่มีขนาดเล็กลง 0.5 KB

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

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

ในแอปพลิเคชันในโลกแห่งความเป็นจริง คอมโพเนนต์มักจะใหญ่กว่ามาก และการโหลดแบบ Lazy จะช่วยลดเพย์โหลด JavaScript เริ่มต้นได้หลายร้อยกิโลไบต์

การนำเข้าแบบไดนามิกที่มีตัวบ่งชี้การโหลดที่กำหนดเอง

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

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

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

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

  2. กด `Control+Shift+J` (หรือ `Command+Option+J` ใน Mac) เพื่อเปิด DevTools

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

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

  5. ในรายการแบบเลื่อนลงการจำกัดอัตรา ให้เลือก 3G เร็ว

  6. กดปุ่ม Click me

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

หน้าจอมืดที่มีข้อความ

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

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

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

บทสรุป

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