หน้าเว็บและแอปพลิเคชันส่วนใหญ่ประกอบด้วยส่วนต่างๆ มากมาย การแยก JavaScript ออกเป็นหลายๆ ชิ้นจะช่วยปรับปรุงประสิทธิภาพของหน้าเว็บได้ แทนที่จะส่ง JavaScript ทั้งหมดที่ประกอบกันเป็นแอปพลิเคชันทันทีที่โหลดหน้าแรก
Codelab นี้แสดงวิธีใช้การแยกโค้ดเพื่อปรับปรุงประสิทธิภาพของ แอปพลิเคชันอย่างง่ายที่จัดเรียงตัวเลข 3 ตัว
วัดผล
เช่นเคย สิ่งสำคัญคือต้องวัดประสิทธิภาพของเว็บไซต์ก่อนที่จะพยายามเพิ่มการเพิ่มประสิทธิภาพใดๆ
- หากต้องการดูตัวอย่างเว็บไซต์ ให้กดดูแอป แล้วกด
เต็มหน้าจอ
- กด `Control+Shift+J` (หรือ `Command+Option+J` ใน Mac) เพื่อเปิด DevTools
- คลิกแท็บเครือข่าย
- เลือกช่องทำเครื่องหมายปิดใช้แคช
- โหลดแอปซ้ำ
JavaScript ขนาด 71.2 KB เพียงเพื่อจัดเรียงตัวเลขไม่กี่ตัวในแอปพลิเคชันง่ายๆ What gives?
ในซอร์สโค้ด (src/index.js
) มีการนำเข้าและใช้ไลบรารี lodash
ในแอปพลิเคชันนี้ Lodash มีฟังก์ชันยูทิลิตีที่มีประโยชน์มากมาย
แต่ที่นี่ใช้เพียงเมธอดเดียวจากแพ็กเกจ
การติดตั้งและนำเข้าการขึ้นต่อกันทั้งหมดของบุคคลที่สามในกรณีที่ใช้เพียงบางส่วน
เป็นข้อผิดพลาดที่พบบ่อย
เพิ่มประสิทธิภาพ
การลดขนาดแพ็กเกจทำได้ 2-3 วิธีดังนี้
- เขียนวิธีการจัดเรียงที่กำหนดเองแทนการนำเข้าไลบรารีของบุคคลที่สาม
- ใช้วิธี
Array.prototype.sort()
ในตัวเพื่อจัดเรียงตามตัวเลข - นำเข้าเฉพาะเมธอด
sortBy
จากlodash
เท่านั้น ไม่ใช่นำเข้าทั้งไลบรารี - ดาวน์โหลดโค้ดสำหรับการจัดเรียงเมื่อผู้ใช้คลิกปุ่มเท่านั้น
ตัวเลือกที่ 1 และ 2 เป็นวิธีที่เหมาะสมอย่างยิ่งในการลดขนาดแพ็กเกจ (และน่าจะเป็นวิธีที่สมเหตุสมผลที่สุดสำหรับแอปพลิเคชันจริง) อย่างไรก็ตาม เราจะไม่ใช้ในบทแนะนำนี้เพื่อวัตถุประสงค์ในการสอน 😈
ทั้งตัวเลือกที่ 3 และ 4 จะช่วยปรับปรุงประสิทธิภาพของแอปพลิเคชันนี้ ส่วนถัดไปของโค้ดแล็บนี้จะครอบคลุมขั้นตอนเหล่านี้ เช่นเดียวกับบทแนะนำการเขียนโค้ด อื่นๆ ให้ลองเขียนโค้ดด้วยตนเองเสมอแทนการคัดลอกและวาง
นำเข้าเฉพาะสิ่งที่ต้องการ
คุณต้องแก้ไขไฟล์บางไฟล์เพื่อนำเข้าเฉพาะวิธีการเดียวจาก lodash
ก่อนอื่น ให้แทนที่การอ้างอิงนี้ใน package.json
"lodash": "^4.7.0",
ด้วยสิ่งต่อไปนี้
"lodash.sortby": "^4.7.0",
ตอนนี้ใน src/index.js
ให้นำเข้าโมดูลนี้โดยเฉพาะ
import "./style.css";
import _ from "lodash";
import sortBy from "lodash.sortby";
และอัปเดตวิธีจัดเรียงค่าดังนี้
form.addEventListener("submit", e => {
e.preventDefault();
const values = [input1.valueAsNumber, input2.valueAsNumber, input3.valueAsNumber];
const sortedValues = _.sortBy(values);
const sortedValues = sortBy(values);
results.innerHTML = `
<h2>
${sortedValues}
</h2>
`
});
โหลดแอปพลิเคชันซ้ำ เปิดเครื่องมือสำหรับนักพัฒนาเว็บ แล้วดูแผงเครือข่ายอีกครั้ง
สําหรับแอปพลิเคชันนี้ เราลดขนาด Bundle ได้มากกว่า 4 เท่าโดยใช้ความพยายามเพียงเล็กน้อย แต่ก็ยังมีโอกาสปรับปรุงได้อีก
การแยกโค้ด
webpack เป็นหนึ่งในเครื่องมือจัดกลุ่มโมดูลโอเพนซอร์สที่ได้รับความนิยมมากที่สุดในปัจจุบัน กล่าวโดยย่อคือ Bundler จะรวมโมดูล JavaScript ทั้งหมด (รวมถึงชิ้นงานอื่นๆ) ที่ประกอบกันเป็นเว็บแอปพลิเคชันไว้ในไฟล์แบบคงที่ที่เบราว์เซอร์อ่านได้
แพ็กเกจเดียวที่ใช้ในแอปพลิเคชันนี้สามารถแบ่งออกเป็น 2 ก้อนแยกกันได้ดังนี้
- หนึ่งคือผู้รับผิดชอบโค้ดที่ประกอบกันเป็นเส้นทางเริ่มต้นของเรา
- ก้อนข้อมูลรองที่มีโค้ดการจัดเรียง
การใช้การนำเข้าแบบไดนามิกช่วยให้โหลดแบบ Lazy Loading หรือ โหลดตามต้องการได้ ในแอปพลิเคชันนี้ ระบบจะโหลดโค้ดที่ประกอบกันเป็นก้อนได้ก็ต่อเมื่อผู้ใช้กดปุ่มเท่านั้น
เริ่มด้วยการนำการนำเข้าระดับบนสุดสำหรับเมธอดการจัดเรียงใน src/index.js
ออก
import sortBy from "lodash.sortby";
และนำเข้าภายใน Listener เหตุการณ์ที่เริ่มทำงานเมื่อกดปุ่ม
form.addEventListener("submit", e => {
e.preventDefault();
import('lodash.sortby')
.then(module => module.default)
.then(sortInput())
.catch(err => { alert(err) });
});
ฟีเจอร์ import()
เป็นส่วนหนึ่งของข้อเสนอ (ปัจจุบันอยู่ในขั้นตอนที่ 3 ของกระบวนการ TC39) เพื่อรวมความสามารถในการนำเข้าโมดูลแบบไดนามิก
webpack ได้รวมการรองรับฟีเจอร์นี้ไว้แล้วและใช้ไวยากรณ์เดียวกันกับที่ระบุไว้ในข้อเสนอ
import()
จะแสดงผล Promise และเมื่อ Promise แก้ไขแล้ว ระบบจะแสดงโมดูลที่เลือก
ซึ่งแยกออกเป็นก้อนแยกต่างหาก หลังจากส่งคืนโมดูลแล้ว module.default
จะใช้เพื่ออ้างอิงการส่งออกเริ่มต้นที่ lodash จัดเตรียมไว้
โดยจะมีการเชื่อมโยง Promise กับ .then
อีกรายการหนึ่งซึ่ง
เรียกใช้เมธอด sortInput
เพื่อจัดเรียงค่าอินพุตทั้ง 3 ค่า ที่ส่วนท้ายของ
Promise Chain .catch()
ใช้เพื่อจัดการกรณีที่สัญญาถูกปฏิเสธ
เนื่องจากข้อผิดพลาด
สิ่งสุดท้ายที่ต้องทำคือเขียนเมธอด sortInput
ที่ส่วนท้ายของไฟล์ โดยต้องเป็นฟังก์ชันที่แสดงผลฟังก์ชันที่
รับเมธอดที่นำเข้าจาก lodash.sortBy
จากนั้นฟังก์ชันที่ซ้อนกันจะ
จัดเรียงค่าอินพุตทั้ง 3 ค่าและอัปเดต DOM
const sortInput = () => {
return (sortBy) => {
const values = [
input1.valueAsNumber,
input2.valueAsNumber,
input3.valueAsNumber
];
const sortedValues = sortBy(values);
results.innerHTML = `
<h2>
${sortedValues}
</h2>
`
};
}
ตรวจสอบ
โหลดแอปพลิเคชันซ้ำอีกครั้งและจับตาดูแผงเครือข่าย อีกครั้ง ระบบจะดาวน์โหลดเฉพาะ Bundle เริ่มต้นขนาดเล็กทันทีที่แอป โหลด
หลังจากกดปุ่มเพื่อจัดเรียงตัวเลขที่ป้อน ระบบจะดึงข้อมูลและเรียกใช้ก้อนข้อมูลที่มีโค้ดการจัดเรียง
สังเกตว่าระบบยังคงจัดเรียงตัวเลข
บทสรุป
การแยกโค้ดและการโหลดแบบ Lazy Loading เป็นเทคนิคที่มีประโยชน์อย่างยิ่งในการลดขนาด ของ Bundle เริ่มต้นของแอปพลิเคชัน ซึ่งจะส่งผลโดยตรงให้ เวลาในการโหลดหน้าเว็บเร็วขึ้นมาก อย่างไรก็ตาม มีสิ่งสำคัญบางอย่างที่ต้องพิจารณาก่อนที่จะรวมการเพิ่มประสิทธิภาพนี้ไว้ในแอปพลิเคชัน
UI การโหลดแบบ Lazy Loading
เมื่อโหลดโค้ดบางโมดูลแบบ Lazy Loading คุณควรพิจารณาว่าผู้ใช้ที่มีการเชื่อมต่อเครือข่ายไม่เสถียรจะได้รับ ประสบการณ์การใช้งานอย่างไร การแยกและ โหลดโค้ดจำนวนมากเมื่อผู้ใช้ส่งการดำเนินการอาจทำให้ดูเหมือนว่าแอปพลิเคชันหยุดทำงาน ดังนั้นให้พิจารณาแสดง ตัวบ่งชี้การโหลดบางอย่าง
การโหลดโมดูลโหนดของบุคคลที่สามแบบ Lazy Loading
การโหลดทรัพยากร Dependency ของบุคคลที่สามแบบเลซี่ในแอปพลิเคชันอาจไม่ใช่แนวทางที่ดีที่สุดเสมอไป และขึ้นอยู่กับว่าคุณใช้ทรัพยากรเหล่านั้นที่ใด โดยปกติแล้ว ระบบจะแยกการขึ้นต่อกับบุคคลที่สาม
ออกเป็นvendor
แพ็กเกจแยกต่างหากที่แคชได้เนื่องจาก
ไม่ได้อัปเดตบ่อยนัก อ่านเพิ่มเติมเกี่ยวกับวิธีที่ SplitChunksPlugin ช่วยคุณทำสิ่งนี้ได้
การโหลดเมื่อจำเป็นด้วยเฟรมเวิร์ก JavaScript
เฟรมเวิร์กและไลบรารียอดนิยมหลายรายการที่ใช้ webpack มีการแยกส่วนเพื่อ ทำให้การโหลดแบบ Lazy ง่ายกว่าการใช้การนำเข้าแบบไดนามิกในส่วนกลางของ แอปพลิเคชัน
- โมดูลการโหลดแบบ Lazy Loading ด้วย Angular
- การแยกโค้ดด้วย React Router
- การโหลดแบบ Lazy Loading ด้วย Vue Router
แม้ว่าการทำความเข้าใจวิธีการทำงานของการนำเข้าแบบไดนามิกจะมีประโยชน์ แต่ให้ใช้วิธีที่เฟรมเวิร์ก/ไลบรารีแนะนำเสมอเพื่อโหลดโมดูลที่เฉพาะเจาะจงแบบ Lazy Load
การโหลดล่วงหน้าและการดึงข้อมูลล่วงหน้า
หากเป็นไปได้ ให้ใช้ประโยชน์จากคำแนะนำของเบราว์เซอร์ เช่น <link rel="preload">
หรือ <link rel="prefetch">
เพื่อลองโหลดโมดูลที่สำคัญให้เร็วขึ้น webpack รองรับคำแนะนำทั้ง 2 รายการผ่านการใช้ความคิดเห็นแบบพิเศษในคำสั่งนำเข้า ซึ่งอธิบายไว้อย่างละเอียดในคู่มือโหลดล่วงหน้าสำหรับก้อนข้อมูลที่สำคัญ
การโหลดแบบ Lazy Loading มากกว่าโค้ด
รูปภาพอาจเป็นส่วนสำคัญของแอปพลิเคชัน การโหลดแบบ Lazy Loading สำหรับรูปภาพที่อยู่ ใต้พับหน้าเว็บหรืออยู่นอกวิวพอร์ตของอุปกรณ์จะช่วยเพิ่มความเร็วของเว็บไซต์ได้ อ่านข้อมูลเพิ่มเติมเกี่ยวกับเรื่องนี้ได้ในคู่มือ Lazysizes