การเพิ่มประสิทธิภาพเนื้อหา JavaScript สำหรับ Page Speed
เผยแพร่แล้ว: 2020-05-05ตัวอย่างด้านล่างมาจากเว็บไซต์ข่าวขนาดใหญ่และซับซ้อน พวกเขาสูญเสียการเข้าชมแบบอินทรีย์มาหลายปีแล้ว DOMContentLoaded Event ของพวกเขาคือ 2615.2 MS คุณอาจคิดว่าขนาด DOM ของพวกเขาใหญ่มาก แต่ไม่มี...
เกือบจะเหมือนกับที่ Google แนะนำ และมีเพียง 1230 โหนด HTML ที่มีอยู่ในเอกสารนี้
คุณสามารถคำนวณเวลาและกระบวนการ domContentLoaded Event และเปรียบเทียบกับคู่แข่งของคุณโดยใช้ DevTools
การตรวจสอบตัวอย่างนี้แสดงให้เห็นว่าขนาด DOM ไม่จำเป็นต้องเป็นจุดวิกฤต ปัญหาหลักอยู่ที่การเรียง ลำดับทรัพยากร : ส่วนสีน้ำเงินใน “แท็บหลัก” มีไว้สำหรับการแยกวิเคราะห์ HTML อย่างไรก็ตาม เว็บไซต์นี้ขัดจังหวะเบราว์เซอร์ด้วยการแสดงผล JavaScript ก่อนที่กระบวนการแยกวิเคราะห์ HTML จะเสร็จสิ้น
(คุณสามารถใช้ส่วน Call Tree ได้เช่นกันเพื่อช่วยค้นหาข้อผิดพลาดที่คล้ายกันสำหรับทีมไอทีของคุณ)
ตัวอย่างนี้แสดงให้เห็นอย่างชัดเจนถึงความสำคัญของการเพิ่มประสิทธิภาพเนื้อหา JavaScript และสิ่งที่อาจผิดพลาดได้เมื่อคุณละเลย JavaScript ในการเพิ่มประสิทธิภาพความเร็วหน้าเว็บของคุณ
นี่เป็นครั้งที่สามในชุดบทความสี่บทความ เพื่อให้เข้าใจบทความนี้มากขึ้น คุณอาจต้องการอ่านบทความสองข้อแรกของชุดข้อมูลนี้:
- การเรนเดอร์จาวาสคริปต์และความเร็วเพจนั้นสัมพันธ์อย่างใกล้ชิดกับวิธีที่เอ็นจินการเรนเดอร์ของเบราว์เซอร์สร้างหน้าเว็บ
- คุณควรเข้าใจเมตริกความเร็วหน้าเว็บขั้นสูงก่อนที่จะเข้าสู่บทความนี้
ฉันจะใช้ตัวอย่างบางส่วนจากสองบทความแรกเพื่อช่วยให้บริบทในบทความนี้
Javascript Rendering คืออะไรและส่งผลต่อความเร็วหน้าเว็บของคุณอย่างไร
การแสดงผล Javascript คือส่วนการโหลดหน้าสุดท้ายที่สามารถเปลี่ยนโครงสร้างที่สร้างขึ้นโดยใช้ DOM และ CSSOM แบบโต้ตอบได้ องค์ประกอบของหน้าใดๆ สามารถเปลี่ยนแปลงได้ในรูปแบบที่ผู้ใช้เรียกใช้หรือแสดงได้ตามปกติ องค์ประกอบใดๆ ที่มีคุณสมบัติ display:none ที่ไม่สามารถเข้าถึงได้โดยแผนผังการแสดงผล สามารถแสดงผลด้วย JavaScript หรือแทรกผ่านองค์ประกอบ HTML ต่างๆ ลงใน DOM
JavaScript ขัดจังหวะ DOM และ CSSOM เนื่องจากจะเปลี่ยน DOM และ CSSOM ในเวลาที่เบราว์เซอร์อ่าน ดังนั้น เพื่อป้องกันไม่ให้ส่งผลกระทบด้านลบต่อเวลาและความเร็วในการโหลดหน้าเว็บ จึงจำเป็นต้องตรวจสอบความสัมพันธ์ระหว่างการแสดงผล DOM, CSSOM และ JavaScript
ด้านบนเป็นตัวอย่างของการสร้างต้นไม้ ข้อมูลโค้ดที่เชื่อมต่อกันทั้งหมดในโหนด CSSOM และ HTML มีความหมายเทียบเท่ากันในแผนผังการแสดงผล หากสังเกตดีๆ คุณจะสังเกตเห็นว่าโหนด HTML "ปุ่มดำเนินการ" ไม่อยู่ในแผนผังการแสดงผล สาเหตุหลักคือ “display:none;” คุณสมบัติ CSS เนื่องจากคำสั่งการล่องหนนี้ คำสั่งจึงไม่รวมอยู่ในแผนผังการแสดงผล หากต้องการดูองค์ประกอบในต้นไม้ต้นนี้ คุณอาจต้องการอ่านบทความแรกในชุดนี้
หากคุณมีองค์ประกอบของหน้าจำนวนมากที่จะไม่ปรากฏในการโหลดครั้งแรกเนื่องจากขึ้นอยู่กับพฤติกรรมของผู้ใช้ ในลำดับการโหลดทรัพยากร คุณจะต้องแยกรายการเหล่านี้และวางไว้ในแถวสุดท้าย การใช้ Shadow DOM หรือ DOM เสมือนเป็นตัวเลือกที่ดีกว่าในตอนนี้
แอตทริบิวต์ Defer และ Async สำหรับทรัพยากร JavaScript
หากคุณใส่ไฟล์ JS ของคุณลงในส่วน และถ้าคุณไม่ใช้แอตทริบิวต์ 'defer' หรือ 'async' อาจทำให้ DOMContentLoaded ของคุณล่าช้า เพื่อป้องกันสถานการณ์นี้ เราอาจใช้แอตทริบิวต์ทั้งสองนี้ Defer คือการชะลอกระบวนการโหลดของไฟล์ JS ในขณะที่ 'Async' คือการโหลด JS และแหล่งอื่น ๆ ในลักษณะคู่ขนาน มีทั้งข้อดีและข้อเสีย เราจะพูดถึงเรื่องหลักเท่านั้นที่นี่
- หากคุณใช้ defer ในไฟล์ JS หลัก คุณอาจไม่เห็นเอฟเฟกต์ 'initiator' จนกว่าจะทำการติดตั้ง
- หากคุณใช้การเลื่อนเวลามากเกินไป อาจทำให้เกิดปัญหาคอขวดของ CPU เมื่อสิ้นสุดการโหลดหน้า
เนื่องจากบทความนี้เขียนขึ้น จึงมีการเผยแพร่การอัปเดต Chrome 80 ในคอลัมน์ Initiator ในตอนนี้ ง่ายกว่ามากในการดูว่าทรัพยากรใดถูกเรียกใช้โดยทรัพยากรใด ตัวอย่างเช่น คุณสามารถเห็นภาพหรือไฟล์ CSS ที่ JS เรียก หากคุณเลื่อนดูทรัพยากรโดยกดปุ่ม shift ค้างไว้ คุณจะเห็นว่าทรัพยากรใดไม่สามารถใช้งานได้โดยไม่ต้องโหลดทรัพยากรอื่น
การเลื่อนในขณะที่กดปุ่ม Shift ค้างไว้: สีแดงหมายถึงทรัพยากรแบบมีเงื่อนไขสำหรับทรัพยากรที่ไฮไลต์ด้วยสีเขียว
คุณยังสามารถใช้ส่วน Initiator ใหม่จาก Chrome เพื่อดูรายละเอียดลำดับการโหลดทรัพยากร ตัวเริ่มต้น และการตรวจสอบลำดับความสำคัญได้ วิธีนี้ช่วยให้คุณตรวจจับสายการเรียก JS ที่ยาวและมีค่าใช้จ่ายสูงได้ เช่น ด้านล่าง
ตัวอย่างของห่วงโซ่การโทร JS ที่ยาวและมีค่าใช้จ่ายสูงจากไซต์เดียวกัน เหนือทรัพยากรที่เลือกคือผู้ริเริ่ม ส่วนถัดไปแสดงทรัพยากรที่เริ่มต้นโดยทรัพยากรที่เลือก
- ไฟล์ JS ที่เลื่อนออกไปจะถูกดาวน์โหลดหลังจากเหตุการณ์ domInteractive ดังนั้นคุณต้องเลือกไฟล์เหล่านี้ตามไฟล์ CSS และรูปภาพของคุณ
- หากคุณเลื่อนไฟล์ JS บุคคลที่สามที่ติดตามผู้ใช้ออก คุณอาจไม่สามารถติดตามพฤติกรรมผู้ใช้บางอย่างได้
- โดยปกติ Defer จะไม่บล็อกกระบวนการ DOM แต่ Async บล็อก ไฟล์ JS ที่มีแอตทริบิวต์ async จะถูกดาวน์โหลดโดยเบราว์เซอร์ระหว่างการแยกวิเคราะห์ HTML และการประมวลผล CSSOM
- หากคุณใช้แอตทริบิวต์ async มากเกินไป คุณอาจสร้างปัญหาคอขวดในการประมวลผลของ CPU และจะทำให้กระบวนการ DOM และ CSSOM ช้าลง คุณต้องเลือกอย่างระมัดระวังว่าจะเลื่อนหรือเปลี่ยนอะไร
นี่คือตัวอย่างรูปแบบสำหรับแอตทริบิวต์ async และ defer โหลดอันแรกก่อน domContentLoaded โดยไม่แยกวิเคราะห์ HTML ระหว่างการดึงข้อมูล ในวินาที ไฟล์ JS ที่ดึงมาจะไม่ถูกดำเนินการก่อนที่การแยกวิเคราะห์ HTML จะเสร็จสิ้น
คำแนะนำและเคล็ดลับสำหรับการแสดงผลและประสิทธิภาพ Javascript
ก่อนเริ่มใช้งานตัวอย่าง ต่อไปนี้คือคำแนะนำบางประการในการปรับปรุงประสิทธิภาพการเรนเดอร์ JavaScript นอกจากนี้ยังอาจช่วยให้เข้าใจความเร็วของหน้าเว็บได้ดีขึ้นและวิธีการทำงานของเบราว์เซอร์
อย่าใช้ตัวแปรที่ไม่จำเป็น
หากคุณเป็น SEO คุณอาจสังเกตเห็นตัวแปรที่ไม่จำเป็นหรือไม่ได้ใช้ในไฟล์ JavaScript มีเครื่องมือมากมายที่สามารถใช้ตรวจจับข้อผิดพลาดประเภทนี้ได้ คุณจะพบตัวอย่างพื้นฐานสองตัวอย่างสำหรับตัวแปรที่ไม่ได้ใช้และตัวแปรที่ไม่จำเป็นด้านล่าง
var carName= ยี่ห้อ+ ” ” + ปี;
document.getElementById(“demo”).innerHTML = carName;
ในที่นี้ ตัวแปร “carName” นั้นไม่จำเป็น คุณสามารถแนะนำการแก้ไขต่อไปนี้:
document.getElementById(“demo”).innerHTML = brand+ ” ” + year
หรือ:
[a, b, c, d, e].forEach(ฟังก์ชัน (ค่า, ดัชนี) {
console.log (ดัชนี);
});
ที่นี่ไม่จำเป็นต้องใช้พารามิเตอร์ "ค่า" เนื่องจากไม่ได้ใช้งาน คุณสามารถลบออกได้:
[a, b, c, d, e].forEach(ฟังก์ชัน (ดัชนี) {
console.log (ดัชนี);
});
ทางด้านขวา คุณจะเห็นเวลาเชื่อมต่อที่นานขึ้น (เส้นสีขาว) และไฟล์ CSS และ JS ถูกโหลดในลำดับที่ไม่สมมาตรด้วย Javascript "async"
ทางด้านซ้าย เวลาเชื่อมต่อจะสั้นลง และไฟล์ CSS และ JS จะไม่ผสมกัน เนื่องจากแต่ละแหล่งโหลดเป็นแถว แอตทริบิวต์ Async สามารถลดดัชนีความเร็วของคุณเนื่องจากสามารถขยายเวลา TBT ได้ ดังนั้นคุณต้องดำเนินการตรวจสอบและรายงานไปยังทีมนักพัฒนาของคุณสำหรับไฟล์ JS ตัวติดตามประสิทธิภาพจากแท็บประสิทธิภาพ หรือคุณสามารถทำการทดสอบด้วยตัวเอง
ใช้เครื่องมือสำหรับงานยาก
สำหรับผู้เริ่มต้นในโค้ด การค้นหาตัวแปรที่ไม่จำเป็นหรือไม่ได้ใช้อาจเป็นเรื่องยาก คุณอาจต้องการใช้เครื่องมือบางอย่างสำหรับงานเหล่านี้ เช่น Chrome DevTools หรือแพ็คเกจ Node.js เช่น Unused (Kami/node-unused: โมดูลที่รายงานกำหนดไว้ แต่ตัวแปรที่ไม่ได้ใช้ในโค้ดของคุณ หรือสำหรับตัวแปรที่ไม่ได้ใช้เพิ่มเติม) หากคุณพบข้อผิดพลาดแม้เพียงเล็กน้อย ฉันเชื่อว่าทีมไอทีของคุณจะรับฟังคุณเพื่อทำให้ไฟล์ JavaScript ของคุณดีขึ้น
การใช้รายงานความครอบคลุมของ Chrome DevTools เพื่อค้นหาโค้ด JavaScript ที่ไม่ได้ใช้
รายงานความครอบคลุมของ Chrome DevTools แสดงข้อมูลโค้ด JavaScript ที่ไม่ได้ใช้ แต่ไม่สามารถใช้งานได้จริง คุณอาจคิดว่าคุณสามารถลบทุกส่วนสีแดงออกจากโค้ดได้ แต่มันไม่ใช่... แต่คุณควรหาฟังก์ชันหรือตัวแปรที่ไม่ได้ใช้โดยสมบูรณ์สำหรับหน้าหมวดหมู่จำนวนมาก ด้วยวิธีนี้ ทีมนักพัฒนาของคุณสามารถโน้มน้าวใจให้ใช้กระบวนการ TreeShaking
TreeShaking หมายถึงการลบโค้ดที่ไม่ทำงานออกจากไฟล์ ฉันแนะนำให้เรียนรู้โดยใช้ตัวแปร JS ที่ไม่ได้ใช้และแพ็คเกจตัวค้นหาฟังก์ชันเพื่อให้ได้เวลา
ขนาด DOM ที่เล็กลงจะช่วยในการแสดงผล JavaScript ทุกคำสั่ง (getElementsByTagName) จะสแกน DOM ของคุณ ขนาด DOM ที่เล็กกว่าจะต้องการทรัพยากรน้อยลงจากเบราว์เซอร์และ CPU/เครือข่ายของอุปกรณ์เมื่อแสดงผล JavaScript
ด้วยการอัปเดต Chrome 80 ใหม่ รายงานความครอบคลุมก็มีการเปลี่ยนแปลงเช่นกัน พวกเขาได้เพิ่มตัวเลือกต่อฟังก์ชั่นและต่อบล็อกเสริม Per Block เป็นค่าเริ่มต้นที่นี่
หากคุณเลือกตามฟังก์ชัน คุณจะเห็นความแตกต่างอย่างมากในรายงานของคุณ เหตุผลหลักสำหรับสถานการณ์นี้คือมุมมองต่อฟังก์ชันจะตรวจสอบว่าฟังก์ชันทั้งหมดกำลังถูกใช้อยู่หรือไม่ หากมีการใช้ฟังก์ชัน 95% ตัวเลือกต่อฟังก์ชันจะกำหนดเป็นโค้ดที่ไม่ได้ใช้เนื่องจากไม่ได้ใช้โค้ด 5% แม้ว่าจะมีการใช้ฟังก์ชันจำนวนมากก็ตาม
บีบอัด ย่อ หรือ Uglify ไฟล์ JS ของคุณ
สามารถทำได้สองวิธี ขั้นแรก ให้ลบช่องว่างและความคิดเห็นที่ไม่จำเป็น ประการที่สอง ใช้ตัวดำเนินการ JavaScript ที่ปรับปรุงแล้วสำหรับไฟล์ JS ของคุณและจัดการชื่อ ตัวแปร ฟังก์ชันต่างๆ ด้วยเทคโนโลยีที่พร้อมใช้งาน
คุณควรรู้เกี่ยวกับ Arrow Functions สำหรับการบีบอัดประเภทนี้ ตัวอย่างเช่น แทนที่จะเป็นตัวอย่าง 84 อักขระนี้:
ฟังก์ชั่นลูกศร Islev (a, b) {
console.log (a + b);
}
ลูกศรFonksiyon (5, 6);
คุณสามารถบีบอัดให้เหลือเพียง 50 ตัวอักษรด้วยฟังก์ชั่นลูกศร =>
const ab = (a, b) => b + a;
console.log (ab (5, 6));
วิธีย่อ/บีบอัดอีกวิธีหนึ่งใช้ได้กับคำสั่ง if แทนที่จะเป็นข้อมูลโค้ด 63 ตัว:
ถ้า (a<b) {
console.log(ab);
}
อื่น {
console.log(a+b);
คุณสามารถใช้อักขระ 43 ตัวด้านล่าง:
(a<b) ? console.log(ab) : console.log(a+b);
คุณยังสามารถแนะนำให้ทีมไอทีของคุณใช้เครื่องหมาย $ และ _ ในการบีบอัดได้อีกด้วย ไฟล์ JavaScript ส่วนใหญ่ทำงานเพื่อตีความ DOM ใหม่ สำหรับสิ่งนี้ คุณอาจเห็น document.getElementById(x); ข้อมูลโค้ดในไฟล์ คุณสามารถใช้เครื่องหมาย $ สำหรับงานนี้ สิ่งนี้จะช่วยคุณประหยัดจากกองขนาดใหญ่ที่ไร้ประโยชน์
ไลบรารี JavaScript ส่วนใหญ่ใช้ $ เป็นค่าเริ่มต้นสำหรับการกำหนดฟังก์ชัน แต่ไม่ใช่ทั้งหมด เนื่องจาก $ เป็นอักขระที่เป็นตัวอักษรเช่นกัน
ในสถานการณ์นี้ คุณอาจแนะนำให้ทีมไอทีของคุณใช้:
ฟังก์ชั่น $(x) {ส่งคืน document.getElementById(x);}
ใช้ประเภทการแสดงผลที่เหมาะสม
ประเภทการแสดงผล JavaScript และหน้าเว็บในแง่ของความเข้ากันได้ของ SEO
SSR Hydration หมายความว่าส่วนประกอบ JS บางตัวจะแสดงผลโดยใช้ Client Side Rendering มีประโยชน์สำหรับ FP และ FMP แต่อาจมีข้อเสียบางประการสำหรับคะแนน TTI และดัชนีความเร็ว
ที่มาของรูปภาพ: Notprovided.eu
แนวทางปฏิบัติที่ดีที่สุดในการเข้ารหัสสำหรับประสิทธิภาพการแสดงผล JavaScript
- การสนับสนุนการบีบอัดที่สำคัญอีกประการหนึ่งจะมาจากการใช้ “_” คุณสามารถใช้ “underscore.js” เพื่อปรับปรุงรูปแบบและฟังก์ชันการเขียน JavaScript ด้วยวิธีนี้ คุณจะสร้างไฟล์ JS ที่มีขนาดเล็กลงในขณะที่จัดการรายการและคอลเล็กชันด้วยฟังก์ชัน JS ที่สั้นกว่าโดยไม่มีฟังก์ชัน JS ในตัว
- การใช้การเปลี่ยนแปลงตัวแปรที่ยาวนานและใช้เวลานานและมลภาวะจากตัวแปรทั่วโลกก็เป็นที่มาของการเรนเดอร์ที่ช้าเช่นกัน คุณควรกำหนดตัวเลือกขอบเขตทั่วไปของฟังก์ชันของคุณและประเภทตัวแปรส่วนกลาง/ตัวแปรแบบยาว การใช้ตัวแปรท้องถิ่นกับ 'Let' จะดีกว่าสำหรับการแสดงผล เนื่องจากตัวแปรในเครื่อง เบราว์เซอร์จะไม่ตรวจสอบตัวแปรฟังก์ชันส่วนกลางอื่นๆ สำหรับการเปลี่ยนแปลงครั้งต่อไป
สำหรับการจำลองการตรวจสอบประสิทธิภาพที่สมจริงยิ่งขึ้น เช่น สิ่งที่คุณอาจเห็นในโทรศัพท์มือถือระดับล่าง คุณควรใช้การตั้งค่าการควบคุม CPU และการตั้งค่าการเชื่อมต่อ 3G แบบเร็ว/ช้าใน Chrome DevTools
ที่มาของภาพ: Addy Osmani
- การใช้ฟังก์ชัน JS ที่เล็กกว่าและเชนตัวแปรจะช่วยประสิทธิภาพการเรนเดอร์ของคุณ นอกจากนี้ การใช้ตัวเลือก "นี้" แทนตัวเลือก "ด้วย" จะดีกว่า ตัวเลือก "นี่" ใน Javascript เป็นโค้ดการทำงานในเครื่องซึ่งแตกต่างจาก "กับ" ตรรกะเดียวกันกับ let และ var ก็ใช้ได้ที่นี่เช่นกัน
- หากคุณใช้ข้อความสั่งของคุณใน For loop code snippets สิ่งนี้จะทำให้ความเร็วในการแสดงผลของคุณช้าลงเล็กน้อย เนื่องจากคำสั่งฟังก์ชันของคุณจะวนซ้ำในแต่ละองค์ประกอบของลูป คุณสามารถสร้างตัวแปรใหม่สำหรับองค์ประกอบลูปและคุณสามารถเรียกองค์ประกอบเหล่านี้ด้วยฟังก์ชันที่อยู่นอกวง For
- หากคุณต้องการเข้าถึงองค์ประกอบ HTML หลายๆ ครั้ง คุณสามารถสร้างตัวแปรสำหรับองค์ประกอบนั้นและเรียกใช้ด้วยฟังก์ชันที่คุณต้องการได้ การเข้าถึงองค์ประกอบ HTML ด้วย JavaScript ไม่ใช่กระบวนการที่รวดเร็ว คุณอาจสร้างภาระให้กับเบราว์เซอร์ของคุณมากขึ้น
อีกวิธีหนึ่งในการปรับปรุงประสิทธิภาพการแสดงผล Javascript คือ Trisomorphic Rendering ผ่าน Service Workers คุณสามารถใส่ไฟล์ JS บางไฟล์ของคุณลงในหน่วยความจำเบราว์เซอร์ของไคลเอ็นต์สำหรับเซสชันในอนาคต วิธีนี้อาจทำให้เว็บไซต์ของคุณทำงานแบบออฟไลน์ได้
คุณสามารถค้นหาตัวอย่างง่ายๆ เพื่อความเข้าใจที่ดีขึ้นและโอกาสในการฝึกฝนกับพนักงานบริการได้ที่นี่
ผูกมันไว้: การเพิ่มประสิทธิภาพ JavaScript และความเร็วของหน้าส่งผลต่อ SEO อย่างไร
เพื่อป้องกันไม่ให้เนื้อหา JavaScript ทำลายความเร็วหน้าเว็บของคุณ เราได้เห็นแล้วว่า Defer และ Async สามารถสร้างความแตกต่างอย่างมากได้อย่างไร นอกจากนี้เรายังได้ดูกลยุทธ์ "การดีบัก" และเคล็ดลับการเขียนโค้ดบางส่วนที่สามารถช่วยคุณปรับปรุงความเร็วของหน้าเว็บด้วยเนื้อหา JavaScript
ตอนนี้เราได้เห็นแล้วว่าเบราว์เซอร์สร้างหน้าเว็บอย่างไร วัดและส่งผลต่อความเร็วของหน้าเว็บอย่างไร และบทบาทของการเพิ่มประสิทธิภาพ JavaScript ในการโหลดหน้าเว็บแล้ว บทความต่อไปจะแสดงให้เห็นว่าลำดับการโหลดทรัพยากรส่งผลต่อความเร็วหน้าเว็บและงบประมาณการรวบรวมข้อมูลอย่างไร
หากคุณสนใจที่จะทบทวนบทความก่อนหน้าในชุดบทความสี่บทความนี้ คุณสามารถค้นหาได้ที่นี่:
- “เบราว์เซอร์สร้างหน้าเว็บอย่างไร”
- “ตัวชี้วัดความเร็วเพจขั้นสูง”