สคริปต์ของบุคคลที่สามส่งผลต่อประสิทธิภาพ คุณจึงควรตรวจสอบสคริปต์เป็นประจำและใช้เทคนิคการโหลดที่มีประสิทธิภาพ Codelab นี้แสดงวิธีเพิ่มประสิทธิภาพการโหลดทรัพยากรของบุคคลที่สาม ซึ่งครอบคลุมเทคนิคต่อไปนี้
การเลื่อนการโหลดสคริปต์
การโหลดทรัพยากรที่ไม่สําคัญแบบ Lazy Loading
การเชื่อมต่อกับต้นทางที่จำเป็นล่วงหน้า
แอปตัวอย่างที่รวมมามีหน้าเว็บง่ายๆ ที่มีฟีเจอร์ 3 รายการจากแหล่งที่มาของบุคคลที่สาม ดังนี้
การฝังวิดีโอ
ไลบรารีการแสดงภาพข้อมูลสำหรับการแสดงผลกราฟเส้น
วิดเจ็ตการแชร์โซเชียลมีเดีย
โดยจะเริ่มด้วยการวัดประสิทธิภาพของแอป จากนั้นจึงใช้เทคนิคแต่ละอย่างเพื่อปรับปรุงประสิทธิภาพของแอปในด้านต่างๆ
วัดประสิทธิภาพ
ก่อนอื่นให้เปิดแอปตัวอย่างในมุมมองแบบเต็มหน้าจอ โดยทำดังนี้
- คลิกรีมิกซ์เพื่อแก้ไขเพื่อให้โปรเจ็กต์แก้ไขได้
- หากต้องการดูตัวอย่างเว็บไซต์ ให้กดดูแอป แล้วกดเต็มหน้าจอ
เรียกใช้การตรวจสอบประสิทธิภาพ Lighthouse ในหน้าเว็บเพื่อสร้างประสิทธิภาพพื้นฐาน
- กดแป้น Control+Shift+J (หรือ Command+Option+J ใน Mac) เพื่อเปิดเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์
- คลิกแท็บ Lighthouse
- คลิกอุปกรณ์เคลื่อนที่
- เลือกช่องทําเครื่องหมายประสิทธิภาพ (คุณสามารถล้างช่องทําเครื่องหมายที่เหลือในส่วนการตรวจสอบได้)
- คลิก3G ที่เร็วจำลอง ชะลอความเร็ว CPU ลง 4 เท่า
- เลือกช่องทำเครื่องหมายล้างพื้นที่เก็บข้อมูล
- คลิกเรียกใช้การตรวจสอบ
เมื่อเรียกใช้การตรวจสอบในเครื่อง ผลลัพธ์ที่แน่นอนอาจแตกต่างกันไป แต่คุณควรสังเกตว่าเวลา First Contentful Paint (FCP) ค่อนข้างสูง และ Lighthouse แนะนํา 2 โอกาสในการตรวจสอบ ได้แก่ นําทรัพยากรที่บล็อกการแสดงผลออกและเชื่อมต่อกับต้นทางที่จําเป็นล่วงหน้า (แม้ว่าเมตริกทั้งหมดจะอยู่ในเกณฑ์ดี แต่การเพิ่มประสิทธิภาพก็ยังคงให้ผลลัพธ์ที่ดีได้)
เลื่อน JavaScript ของบุคคลที่สาม
การตรวจสอบกำจัดทรัพยากรที่บล็อกการแสดงผลระบุว่าคุณสามารถประหยัดเวลาได้ด้วยการเลื่อนใช้สคริปต์ที่มาจาก d3js.org
D3.js เป็นไลบรารี JavaScript สําหรับสร้างการแสดงข้อมูลเป็นภาพ ไฟล์ script.js
ในแอปตัวอย่างใช้ฟังก์ชันยูทิลิตี D3 เพื่อสร้างแผนภูมิเส้น SVG และเพิ่มต่อท้ายหน้า ลำดับการดำเนินการที่นี่มีความสำคัญ script.js
ต้องทำงานหลังจากที่แยกวิเคราะห์เอกสารและโหลดไลบรารี D3 แล้ว จึงมีการรวมไว้ก่อนแท็ก </body>
ที่ปิดใน index.html
อย่างไรก็ตาม สคริปต์ D3 รวมอยู่ใน <head>
ของหน้า ซึ่งบล็อกการแยกวิเคราะห์เอกสารที่เหลือ
แอตทริบิวต์มายากล 2 รายการที่ปลดบล็อกโปรแกรมแยกวิเคราะห์ได้เมื่อเพิ่มลงในแท็กสคริปต์ ได้แก่
async
ช่วยให้มั่นใจว่าสคริปต์จะดาวน์โหลดในเบื้องหลังและดำเนินการในโอกาสแรกหลังจากดาวน์โหลดเสร็จdefer
ช่วยให้มั่นใจได้ว่าสคริปต์จะดาวน์โหลดในเบื้องหลังและดำเนินการหลังจากการแยกวิเคราะห์เสร็จสมบูรณ์
เนื่องจากแผนภูมินี้ไม่สำคัญกับหน้าเว็บโดยรวมมากนักและมักจะอยู่ด้านล่างของหน้า ให้ใช้ defer
เพื่อตรวจสอบว่าไม่มีบล็อกโปรแกรมวิเคราะห์
ขั้นตอนที่ 1: โหลดสคริปต์แบบไม่พร้อมกันโดยใช้แอตทริบิวต์ defer
ในบรรทัด 17 ใน index.html
ให้เพิ่มแอตทริบิวต์ defer
ลงในองค์ประกอบ <script>
ดังนี้
<script src="https://d3js.org/d3.v3.min.js" defer></script>
ขั้นตอนที่ 2: ตรวจสอบลำดับการดำเนินการที่ถูกต้อง
เมื่อเลื่อน D3 ออกไปแล้ว script.js
จะทํางานก่อนที่ D3 จะพร้อมใช้งาน ซึ่งจะทำให้เกิดข้อผิดพลาด
สคริปต์ที่มีแอตทริบิวต์ defer
จะทํางานตามลําดับที่ระบุ โปรดเพิ่ม defer
ลงใน script.js
แล้วย้ายขึ้นไปที่ <head>
ของเอกสารต่อจากองค์ประกอบ D3 <script>
เพื่อให้แน่ใจว่า script.js
จะทำงานหลังจากที่ D3 พร้อมใช้งาน ตอนนี้จะไม่บล็อกโปรแกรมแยกวิเคราะห์อีกต่อไป และการดาวน์โหลดจะเริ่มเร็วขึ้น
<script src="https://d3js.org/d3.v3.min.js" defer></script>
<script src="./script.js" defer></script>
โหลดทรัพยากรของบุคคลที่สามแบบ Lazy Loading
ทรัพยากรทั้งหมดที่อยู่ด้านล่างของหน้าเว็บเหมาะสําหรับการโหลดแบบ Lazy Loading
แอปตัวอย่างมีวิดีโอ YouTube ที่ฝังอยู่ใน iframe วิธีตรวจสอบจำนวนคำขอที่หน้าเว็บส่งและคำขอที่มาจาก iframe ของ YouTube ที่ฝัง
- หากต้องการดูตัวอย่างเว็บไซต์ ให้กดดูแอป แล้วกดเต็มหน้าจอ
- กดแป้น Control+Shift+J (หรือ Command+Option+J ใน Mac) เพื่อเปิดเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์
- คลิกแท็บเครือข่าย
- เลือกช่องทำเครื่องหมายปิดใช้แคช
- เลือก Fast 3G ในเมนูแบบเลื่อนลงการจำกัดความเร็ว
- โหลดหน้าเว็บซ้ำ
แผงเครือข่ายจะแสดงว่าหน้าเว็บส่งคําขอทั้งหมด 28 รายการและโอนทรัพยากรที่บีบอัดแล้วเกือบ 1 MB
หากต้องการระบุคำขอที่ iframe
ของ YouTube ส่ง ให้มองหารหัสวิดีโอ 6lfaiXM6waw
ในคอลัมน์ผู้เริ่ม วิธีจัดกลุ่มคำขอทั้งหมดตามโดเมน
ในแผงเครือข่าย ให้คลิกขวาที่ชื่อคอลัมน์
เลือกคอลัมน์โดเมนในเมนูแบบเลื่อนลง
หากต้องการจัดเรียงคำขอตามโดเมน ให้คลิกชื่อคอลัมน์ Domains
การจัดเรียงใหม่แสดงให้เห็นว่ามีคำขอเพิ่มเติมสำหรับโดเมน Google โดยรวมแล้ว iframe ของ YouTube จะส่งคำขอสคริปต์ สไตล์ชีต รูปภาพ และแบบอักษร 14 รายการ แต่ผู้ใช้ไม่จำเป็นต้องใช้ชิ้นงานทั้งหมดจริงๆ เว้นแต่ว่าผู้ใช้จะเลื่อนลงเพื่อเล่นวิดีโอ
การรอโหลดวิดีโอแบบ Lazy Loading จนกว่าผู้ใช้จะเลื่อนลงไปที่ส่วนนั้นของหน้าเว็บจะช่วยลดจำนวนคำขอที่หน้าเว็บส่งในตอนแรก วิธีนี้จะช่วยประหยัดข้อมูลของผู้ใช้และเพิ่มความเร็วในการโหลดครั้งแรก
วิธีหนึ่งในการใช้การโหลดแบบ Lazy Loading คือการใช้ Intersection Observer ซึ่งเป็น API ของเบราว์เซอร์ที่จะแจ้งให้คุณทราบเมื่อองค์ประกอบเข้าหรือออกจากวิวพอร์ตของเบราว์เซอร์
ขั้นตอนที่ 1: ป้องกันไม่ให้วิดีโอโหลดในตอนแรก
หากต้องการโหลด iframe ของวิดีโอแบบ Lazy Load คุณต้องป้องกันไม่ให้ iframe โหลดตามปกติก่อน โดยแทนที่แอตทริบิวต์ src
ด้วยแอตทริบิวต์ data-src
เพื่อระบุ URL ของวิดีโอ
<iframe width="560" height="315" data-src="https://www.youtube.com/embed/lS9D6w1GzGY" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
data-src
คือแอตทริบิวต์ข้อมูลที่ช่วยให้คุณจัดเก็บข้อมูลเพิ่มเติมในองค์ประกอบ HTML มาตรฐานได้ คุณตั้งชื่อแอตทริบิวต์ข้อมูลเป็นอะไรก็ได้ ตราบใดที่ขึ้นต้นด้วย "data-"
ส่วน iframe ที่ไม่มี src
จะไม่โหลด
ขั้นตอนที่ 2: ใช้ Intersection Observer เพื่อโหลดวิดีโอแบบ Lazy Load
หากต้องการโหลดวิดีโอเมื่อผู้ใช้เลื่อนไปดูวิดีโอ คุณต้องทราบว่าเมื่อใดที่ผู้ใช้เลื่อนไปดูวิดีโอ ด้วยเหตุนี้ Intersection Observer API จึงเข้ามามีบทบาท Intersection Observer API ช่วยให้คุณลงทะเบียนฟังก์ชัน Callback ที่ทำงานทุกครั้งที่องค์ประกอบที่คุณต้องการติดตามเข้าหรือออกจากวิวพอร์ต
วิธีเริ่มต้นใช้งานคือสร้างไฟล์ใหม่และตั้งชื่อว่า lazy-load.js
- คลิกไฟล์ใหม่ แล้วตั้งชื่อ
- คลิกเพิ่มไฟล์นี้
เพิ่มแท็กสคริปต์ลงในส่วนหัวของเอกสาร
<script src="/lazy-load.js" defer></script>
ใน lazy-load.js
ให้สร้าง IntersectionObserver
ใหม่และส่งฟังก์ชัน Callback ให้เพื่อเรียกใช้ ดังนี้
// create a new Intersection Observer
let observer = new IntersectionObserver(callback);
ตอนนี้ให้ observer
ดูองค์ประกอบเป้าหมาย (ในกรณีนี้คือ iframe ของวิดีโอ) โดยส่งเป็นอาร์กิวเมนต์ในเมธอด observe
// the element that you want to watch
const element = document.querySelector('iframe');
// register the element with the observe method
observer.observe(element);
callback
ได้รับรายการออบเจ็กต์ IntersectionObserverEntry
และออบเจ็กต์ IntersectionObserver
เอง แต่ละรายการประกอบด้วยองค์ประกอบ target
และพร็อพเพอร์ตี้ที่อธิบายขนาด ตำแหน่ง เวลาเข้าสู่วิวพอร์ต และอื่นๆ พร็อพเพอร์ตี้หนึ่งของ IntersectionObserverEntry
คือ isIntersecting
ซึ่งเป็นค่าบูลีนที่เท่ากับ true
เมื่อองค์ประกอบเข้าสู่วิวพอร์ต
ในตัวอย่างนี้ target
คือ iframe
isIntersecting
เท่ากับ true
เมื่อ target
เข้าสู่วิวพอร์ต หากต้องการดูวิธีการทํางาน ให้แทนที่ callback
ด้วยฟังก์ชันต่อไปนี้
let observer = new IntersectionObserver(callback);
let observer = new IntersectionObserver(function(entries, observer) {
entries.forEach(entry => {
console.log(entry.target);
console.log(entry.isIntersecting);
});
});
- หากต้องการดูตัวอย่างเว็บไซต์ ให้กดดูแอป แล้วกดเต็มหน้าจอ
- กดแป้น Control+Shift+J (หรือ Command+Option+J ใน Mac) เพื่อเปิดเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์
- คลิกแท็บคอนโซล
ลองเลื่อนขึ้นและลง คุณควรเห็นค่าของ isIntersecting
เปลี่ยนแปลงและองค์ประกอบเป้าหมายบันทึกไว้ในคอนโซล
หากต้องการโหลดวิดีโอเมื่อผู้ใช้เลื่อนไปยังตําแหน่ง ให้ใช้ isIntersecting
เป็นเงื่อนไขในการเรียกใช้ฟังก์ชัน loadElement
ซึ่งจะรับค่าจาก data-src
ขององค์ประกอบ iframe
และตั้งค่าเป็นแอตทริบิวต์ src
ขององค์ประกอบ iframe
การเปลี่ยนทดแทนดังกล่าวจะทริกเกอร์การโหลดวิดีโอ จากนั้นเมื่อวิดีโอโหลดแล้ว ให้เรียกใช้เมธอด unobserve
ใน observer
เพื่อหยุดดูองค์ประกอบเป้าหมาย
let observer = new IntersectionObserver(function (entries, observer) {
entries.forEach(entry => {
console.log(entry.target);
console.log(entry.isIntersecting);
});
});
if (entry.isIntersecting) {
// do this when the element enters the viewport
loadElement(entry.target);
// stop watching
observer.unobserve(entry.target);
}
});
});
function loadElement(element) {
const src = element.getAttribute('data-src');
element.src = src;
}
ขั้นตอนที่ 3: ประเมินประสิทธิภาพอีกครั้ง
หากต้องการดูการเปลี่ยนแปลงขนาดและจํานวนทรัพยากร ให้เปิดแผงเครือข่ายของเครื่องมือสําหรับนักพัฒนาเว็บ แล้วโหลดหน้าเว็บซ้ำอีกครั้ง แผงเครือข่ายจะแสดงว่าหน้าเว็บส่งคําขอ 14 รายการและมีเพียง 260 KB นี่เป็นการพัฒนาที่มีประโยชน์
จากนั้นเลื่อนหน้าเว็บลงและคอยดูแผงเครือข่าย เมื่อไปที่วิดีโอ คุณควรเห็นว่าหน้าเว็บเรียกคําขอเพิ่มเติม
เชื่อมต่อกับต้นทางที่จำเป็นล่วงหน้า
คุณได้เลื่อน JavaScript ที่ไม่สําคัญและโหลดคําขอ YouTube แบบ Lazy ไว้แล้ว ตอนนี้ถึงเวลาเพิ่มประสิทธิภาพเนื้อหาของบุคคลที่สามที่เหลือ
การเพิ่มแอตทริบิวต์ rel=preconnect
ลงในลิงก์จะบอกให้เบราว์เซอร์สร้างการเชื่อมต่อกับโดเมนก่อนที่จะส่งคำขอทรัพยากรนั้น แอตทริบิวต์นี้เหมาะสําหรับต้นทางที่ให้ทรัพยากรที่คุณแน่ใจว่าหน้าเว็บจําเป็นต้องใช้
การตรวจสอบ Lighthouse ที่คุณทําในขั้นตอนแรกตามที่แนะนําในเชื่อมต่อกับต้นทางที่จําเป็นล่วงหน้าระบุว่าคุณสามารถประหยัดเวลาได้ประมาณ 400 มิลลิวินาทีโดยสร้างการเชื่อมต่อล่วงหน้าไปยัง staticxx.facebook.com และ youtube.com
เนื่องจากตอนนี้วิดีโอ YouTube มีการโหลดแบบเลื่อนเวลาไว้ก่อน จึงเหลือเพียง staticxx.facebook.com ซึ่งเป็นแหล่งที่มาของวิดเจ็ตการแชร์โซเชียลมีเดีย การสร้างการเชื่อมต่อกับโดเมนนี้ตั้งแต่เนิ่นๆ นั้นง่ายเพียงเพิ่มแท็ก <link>
ลงใน <head>
ของเอกสาร
<link rel="preconnect" href="https://staticxx.facebook.com">
ประเมินประสิทธิภาพอีกครั้ง
สถานะของหน้าเว็บหลังการเพิ่มประสิทธิภาพ ทําตามขั้นตอนจากส่วนวัดประสิทธิภาพของโค้ดแล็บเพื่อเรียกใช้การตรวจสอบ Lighthouse อีกครั้ง