เพิ่มประสิทธิภาพ 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 ในคอลัมน์ผู้เริ่ม วิธีจัดกลุ่มคำขอทั้งหมดตามโดเมน

  • ในแผงเครือข่าย ให้คลิกขวาที่ชื่อคอลัมน์

  • เลือกคอลัมน์โดเมนในเมนูแบบเลื่อนลง

  • หากต้องการจัดเรียงคำขอตามโดเมน ให้คลิกชื่อคอลัมน์โดเมน

การจัดเรียงใหม่แสดงให้เห็นว่ามีคำขอเพิ่มเติมสำหรับโดเมน 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 Loading แล้ว ตอนนี้ก็ถึงเวลาเพิ่มประสิทธิภาพให้กับเนื้อหาของบุคคลที่สามที่เหลือ

การเพิ่มแอตทริบิวต์ rel=preconnect ลงในลิงก์จะบอกให้เบราว์เซอร์สร้างการเชื่อมต่อกับโดเมนก่อนที่จะส่งคำขอทรัพยากรนั้น แอตทริบิวต์นี้เหมาะสําหรับต้นทางที่ให้ทรัพยากรที่คุณแน่ใจว่าหน้าเว็บจําเป็นต้องใช้

การตรวจสอบ Lighthouse ที่คุณทําในขั้นตอนแรกตามที่แนะนําในเชื่อมต่อกับต้นทางที่จําเป็นล่วงหน้าระบุว่าคุณสามารถประหยัดเวลาได้ประมาณ 400 มิลลิวินาทีโดยสร้างการเชื่อมต่อล่วงหน้าไปยัง staticxx.facebook.com และ youtube.com

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

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

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

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

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

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