เพิ่มประสิทธิภาพ JavaScript ของบุคคลที่สาม

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

  • การเลื่อนการโหลดสคริปต์

  • การโหลดทรัพยากรที่ไม่สําคัญแบบ Lazy Loading

  • การเชื่อมต่อกับต้นทางที่จำเป็นล่วงหน้า

แอปตัวอย่างที่รวมมามีหน้าเว็บง่ายๆ ที่มีฟีเจอร์ 3 รายการจากแหล่งที่มาของบุคคลที่สาม ดังนี้

  • การฝังวิดีโอ

  • ไลบรารีการแสดงภาพข้อมูลสำหรับการแสดงผลกราฟเส้น

  • วิดเจ็ตการแชร์โซเชียลมีเดีย

ภาพหน้าจอของหน้าเว็บที่ไฮไลต์ทรัพยากรของบุคคลที่สาม
ทรัพยากรของบุคคลที่สามในแอปตัวอย่าง

โดยจะเริ่มด้วยการวัดประสิทธิภาพของแอป จากนั้นจึงใช้เทคนิคแต่ละอย่างเพื่อปรับปรุงประสิทธิภาพของแอปในด้านต่างๆ

วัดประสิทธิภาพ

ก่อนอื่นให้เปิดแอปตัวอย่างในมุมมองแบบเต็มหน้าจอ โดยทำดังนี้

  1. คลิกรีมิกซ์เพื่อแก้ไขเพื่อให้โปรเจ็กต์แก้ไขได้
  2. หากต้องการดูตัวอย่างเว็บไซต์ ให้กดดูแอป แล้วกดเต็มหน้าจอ เต็มหน้าจอ

เรียกใช้การตรวจสอบประสิทธิภาพ Lighthouse ในหน้าเว็บเพื่อสร้างประสิทธิภาพพื้นฐาน

  1. กดแป้น Control+Shift+J (หรือ Command+Option+J ใน Mac) เพื่อเปิดเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์
  2. คลิกแท็บ Lighthouse
  3. คลิกอุปกรณ์เคลื่อนที่
  4. เลือกช่องทําเครื่องหมายประสิทธิภาพ (คุณสามารถล้างช่องทําเครื่องหมายที่เหลือในส่วนการตรวจสอบได้)
  5. คลิก3G ที่เร็วจำลอง ชะลอความเร็ว CPU ลง 4 เท่า
  6. เลือกช่องทำเครื่องหมายล้างพื้นที่เก็บข้อมูล
  7. คลิกเรียกใช้การตรวจสอบ

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

ภาพหน้าจอของการตรวจสอบ Lighthouse ที่แสดง FCP 2.4 วินาทีและโอกาส 2 ประการ ได้แก่ กำจัดทรัพยากรที่บล็อกการแสดงผลและเชื่อมต่อกับต้นทางที่จำเป็นล่วงหน้า

เลื่อน JavaScript ของบุคคลที่สาม

การตรวจสอบกำจัดทรัพยากรที่บล็อกการแสดงผลระบุว่าคุณสามารถประหยัดเวลาได้ด้วยการเลื่อนใช้สคริปต์ที่มาจาก d3js.org

ภาพหน้าจอของการตรวจสอบ "กำจัดทรัพยากรที่บล็อกการแสดงผล" โดยไฮไลต์สคริปต์ d3.v3.min.js

D3.js เป็นไลบรารี JavaScript สําหรับสร้างการแสดงข้อมูลเป็นภาพ ไฟล์ script.js ในแอปตัวอย่างใช้ฟังก์ชันยูทิลิตี D3 เพื่อสร้างแผนภูมิเส้น SVG และเพิ่มต่อท้ายหน้า ลำดับการดำเนินการที่นี่มีความสำคัญ script.js ต้องทำงานหลังจากที่แยกวิเคราะห์เอกสารและโหลดไลบรารี D3 แล้ว จึงมีการรวมไว้ก่อนแท็ก </body> ที่ปิดใน index.html

อย่างไรก็ตาม สคริปต์ D3 รวมอยู่ใน <head> ของหน้า ซึ่งบล็อกการแยกวิเคราะห์เอกสารที่เหลือ

ภาพหน้าจอของ index.html ที่มีแท็กสคริปต์ที่ไฮไลต์ในส่วนหัว

แอตทริบิวต์มายากล 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 ที่ฝัง

  1. หากต้องการดูตัวอย่างเว็บไซต์ ให้กดดูแอป แล้วกดเต็มหน้าจอ เต็มหน้าจอ
  2. กดแป้น Control+Shift+J (หรือ Command+Option+J ใน Mac) เพื่อเปิดเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์
  3. คลิกแท็บเครือข่าย
  4. เลือกช่องทำเครื่องหมายปิดใช้แคช
  5. เลือก Fast 3G ในเมนูแบบเลื่อนลงการจำกัดความเร็ว
  6. โหลดหน้าเว็บซ้ำ

ภาพหน้าจอของแผงเครือข่ายในเครื่องมือสําหรับนักพัฒนาเว็บ

แผงเครือข่ายจะแสดงว่าหน้าเว็บส่งคําขอทั้งหมด 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);
    });
  });
  1. หากต้องการดูตัวอย่างเว็บไซต์ ให้กดดูแอป แล้วกดเต็มหน้าจอ เต็มหน้าจอ
  2. กดแป้น Control+Shift+J (หรือ Command+Option+J ใน Mac) เพื่อเปิดเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์
  3. คลิกแท็บคอนโซล

ลองเลื่อนขึ้นและลง คุณควรเห็นค่าของ 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

การตรวจสอบการเชื่อมต่อกับต้นทางที่จำเป็นล่วงหน้าโดยไฮไลต์โดเมน staticxx.facebook.com

เนื่องจากตอนนี้วิดีโอ YouTube มีการโหลดแบบเลื่อนเวลาไว้ก่อน จึงเหลือเพียง staticxx.facebook.com ซึ่งเป็นแหล่งที่มาของวิดเจ็ตการแชร์โซเชียลมีเดีย การสร้างการเชื่อมต่อกับโดเมนนี้ตั้งแต่เนิ่นๆ นั้นง่ายเพียงเพิ่มแท็ก <link> ลงใน <head> ของเอกสาร

  <link rel="preconnect" href="https://staticxx.facebook.com">

ประเมินประสิทธิภาพอีกครั้ง

สถานะของหน้าเว็บหลังการเพิ่มประสิทธิภาพ ทําตามขั้นตอนจากส่วนวัดประสิทธิภาพของโค้ดแล็บเพื่อเรียกใช้การตรวจสอบ Lighthouse อีกครั้ง

การตรวจสอบ Lighthouse ที่แสดง FCP 1 วินาทีและคะแนนประสิทธิภาพ 99