การเพิ่มประสิทธิภาพการโหลดสคริปต์ของบุคคลที่สามใน Next.js

ทำความเข้าใจวิสัยทัศน์เบื้องหลังคอมโพเนนต์สคริปต์ของ Next.js ซึ่งมีโซลูชันในตัวเพื่อเพิ่มประสิทธิภาพการโหลดสคริปต์ของบุคคลที่สาม

ประมาณ 45% ของคำขอจากเว็บไซต์ที่แสดงในอุปกรณ์เคลื่อนที่และเดสก์ท็อปเป็นคำขอของบุคคลที่สาม ซึ่ง 33% เป็นสคริปต์ ขนาด เวลาในการตอบสนอง และการโหลดสคริปต์ของบุคคลที่สามอาจส่งผลต่อประสิทธิภาพของเว็บไซต์ได้อย่างมาก คอมโพเนนต์สคริปต์ Next.js มาพร้อมกับแนวทางปฏิบัติแนะนำและค่าเริ่มต้นที่พร้อมใช้งานเพื่อช่วยนักพัฒนาแอปในการนําสคริปต์ของบุคคลที่สามมาใช้ในแอปพลิเคชันของตน พร้อมทั้งแก้ปัญหาด้านประสิทธิภาพที่อาจเกิดขึ้นได้

สคริปต์ของบุคคลที่สามและผลกระทบต่อประสิทธิภาพ

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

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

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

การตรวจสอบ Lighthouse เพื่อกำจัดทรัพยากรที่บล็อกการแสดงผลและลดการใช้งานของบุคคลที่สาม

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

แม้ว่าจะมีแนวทางปฏิบัติแนะนำในการลดผลกระทบของบุคคลที่สาม แต่ผู้ใช้บางรายอาจไม่ทราบวิธีใช้แนวทางปฏิบัติแนะนำกับบุคคลที่สามทุกรายที่ใช้ การดำเนินการนี้อาจมีความซับซ้อนเนื่องจากสาเหตุต่อไปนี้

  • โดยเฉลี่ยแล้ว เว็บไซต์ใช้บุคคลที่สามที่แตกต่างกัน 21-23 ราย รวมถึงสคริปต์ ในอุปกรณ์เคลื่อนที่และเดสก์ท็อป การใช้งานและคำแนะนำอาจแตกต่างกันไปในแต่ละรายการ
  • การใช้งานบุคคลที่สามหลายรายอาจแตกต่างกันไปโดยขึ้นอยู่กับว่ามีการใช้เฟรมเวิร์กหรือไลบรารี UI ใดหรือไม่
  • มีการเปิดตัวไลบรารีของบุคคลที่สามใหม่ๆ เป็นประจำ
  • ข้อกําหนดทางธุรกิจที่แตกต่างกันซึ่งเกี่ยวข้องกับบุคคลที่สามรายเดียวกันทําให้นักพัฒนาแอปใช้มาตรฐานเดียวกันได้ยาก

ความสนใจของสคริปต์ของบุคคลที่สามใน Aurora

หนึ่งในการทำงานร่วมกันของ Aurora กับเฟรมเวิร์กและเครื่องมือเว็บโอเพนซอร์สคือการมอบเครื่องมือเริ่มต้นที่มีประสิทธิภาพและมีเครื่องมือแสดงความคิดเห็น เพื่อช่วยให้นักพัฒนาซอฟต์แวร์ปรับปรุงประสบการณ์ของผู้ใช้ในด้านต่างๆ เช่น ประสิทธิภาพ การช่วยเหลือพิเศษ การรักษาความปลอดภัย และความพร้อมของอุปกรณ์เคลื่อนที่ ในปี 2021 เรามุ่งเน้นที่การช่วยให้สแต็กเฟรมเวิร์กปรับปรุงประสบการณ์ของผู้ใช้และเมตริก Core Web Vitals

ขั้นตอนที่สําคัญที่สุดอย่างหนึ่งในการบรรลุเป้าหมายเพื่อปรับปรุงประสิทธิภาพเฟรมเวิร์กคือการค้นคว้าลําดับการโหลดสคริปต์ของบุคคลที่สามใน Next.js ที่เหมาะที่สุด เฟรมเวิร์กอย่าง Next.js อยู่ในตําแหน่งที่ไม่ซ้ำใครในการให้ค่าเริ่มต้นและฟีเจอร์ที่มีประโยชน์ซึ่งช่วยให้นักพัฒนาแอปโหลดทรัพยากรได้อย่างมีประสิทธิภาพ รวมถึงทรัพยากรของบุคคลที่สาม เราได้ศึกษาข้อมูล HTTP Archive และ Lighthouse อย่างละเอียดเพื่อค้นหาว่าบุคคลที่สามรายใดบล็อกการแสดงผลมากที่สุดในเฟรมเวิร์กต่างๆ

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

การจัดลําดับสคริปต์ของบุคคลที่สามโดยไม่ใช้คอมโพเนนต์เฟรมเวิร์ก

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

  1. ใช้แอตทริบิวต์ async หรือ defer กับแท็ก <script> ที่บอกให้เบราว์เซอร์โหลดสคริปต์ของบุคคลที่สามที่ไม่สำคัญโดยไม่ต้องบล็อกโปรแกรมแยกวิเคราะห์เอกสาร สคริปต์ที่ไม่จำเป็นสำหรับการโหลดหน้าเว็บครั้งแรกหรือการโต้ตอบของผู้ใช้ครั้งแรกอาจถือว่าไม่สำคัญ

       <script src="https://example.com/script1.js" defer></script>
       <script src="https://example.com/script2.js" async></script>
    
  2. สร้างการเชื่อมต่อกับต้นทางที่จำเป็นล่วงหน้าโดยใช้การเชื่อมต่อล่วงหน้าและการดึงข้อมูล DNS ล่วงหน้า วิธีนี้ช่วยให้สคริปต์ที่สำคัญเริ่มดาวน์โหลดได้เร็วขึ้น

       <head>
           <link rel="preconnect" href="http://PreconnThis.com">
           <link rel="dns-prefetch" href="http://PrefetchThis.com">
       </head>
    
  3. โหลดแบบ Lazy Loading ทรัพยากรและชิ้นงานของบุคคลที่สามหลังจากที่เนื้อหาในหน้าเว็บหลักโหลดเสร็จแล้ว หรือเมื่อผู้ใช้เลื่อนลงไปที่ส่วนที่มีชิ้นงานนั้นๆ

คอมโพเนนต์สคริปต์ Next.js

คอมโพเนนต์สคริปต์ Next.js ใช้เมธอดข้างต้นเพื่อจัดลำดับสคริปต์ และมีเทมเพลตสำหรับนักพัฒนาแอปในการกำหนดกลยุทธ์การโหลด เมื่อระบุกลยุทธ์ที่เหมาะสมแล้ว กลยุทธ์ดังกล่าวจะโหลดอย่างเหมาะสมโดยไม่บล็อกทรัพยากรสําคัญอื่นๆ

คอมโพเนนต์สคริปต์จะอิงตามแท็ก HTML <script> และมีตัวเลือกในการตั้งค่าลําดับความสําคัญในการโหลดสคริปต์ของบุคคลที่สามโดยใช้แอตทริบิวต์ strategy

// Example for beforeInteractive:
<Script src="https://cdnjs.cloudflare.com/polyfill/v3/polyfill.min.js?features=IntersectionObserverEntry%2CIntersectionObserver" strategy="beforeInteractive" />

// Example for afterInteractive (default):
<Script src="https://example.com/samplescript.js" />

// Example for lazyonload:
<Script src="https://connect.facebook.net/en_US/sdk.js" strategy="lazyOnload" />

แอตทริบิวต์กลยุทธ์มี 3 ค่า

  1. beforeInteractive: ตัวเลือกนี้อาจใช้สคริปต์ที่สำคัญซึ่งควรทำงานก่อนที่หน้าเว็บจะโต้ตอบได้ Next.js จะตรวจสอบว่าสคริปต์ดังกล่าวได้รับการแทรกลงใน HTML เริ่มต้นบนเซิร์ฟเวอร์และดำเนินการก่อน JavaScript ที่รวมไว้เองอื่นๆ การจัดการความยินยอม สคริปต์การตรวจจับบ็อต หรือไลบรารีตัวช่วยที่จําเป็นสําหรับแสดงผลเนื้อหาสําคัญเหมาะสําหรับกลยุทธ์นี้

  2. afterInteractive: กลยุทธ์นี้เป็นกลยุทธ์เริ่มต้นและเทียบเท่ากับการโหลดสคริปต์ที่มีแอตทริบิวต์ที่เลื่อนเวลาออกไป ควรใช้สำหรับสคริปต์ที่เบราว์เซอร์สามารถเรียกใช้หลังจากที่หน้าเว็บมีการโต้ตอบ เช่น สคริปต์การวิเคราะห์ Next.js จะแทรกสคริปต์เหล่านี้ฝั่งไคลเอ็นต์และสคริปต์จะทํางานหลังจากที่หน้าเว็บได้รับการไฮเดรต ดังนั้น Next.js จะเลื่อนการโหลดสคริปต์ของบุคคลที่สามทั้งหมดที่กําหนดโดยใช้คอมโพเนนต์สคริปต์ เว้นแต่จะระบุไว้เป็นอย่างอื่น ซึ่งจะเป็นค่าเริ่มต้นที่มีประสิทธิภาพ

  3. lazyOnload: ตัวเลือกนี้อาจใช้เพื่อโหลดสคริปต์ที่มีลําดับความสําคัญต่ำแบบ Lazy Loading เมื่อเบราว์เซอร์ไม่ได้ใช้งาน ฟังก์ชันการทำงานของสคริปต์ดังกล่าวไม่จำเป็นในทันทีหลังจากที่หน้าเว็บมีการโต้ตอบ เช่น แชทหรือปลั๊กอินโซเชียลมีเดีย

นักพัฒนาซอฟต์แวร์สามารถบอก Next.js ว่าแอปพลิเคชันของตนใช้สคริปต์อย่างไรโดยระบุกลยุทธ์ วิธีนี้จะช่วยให้เฟรมเวิร์กใช้การเพิ่มประสิทธิภาพและแนวทางปฏิบัติแนะนำเพื่อโหลดสคริปต์ขณะที่คงลำดับการโหลดที่ดีที่สุดได้

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

การวัดผลกระทบ

เราใช้เทมเพลตสำหรับแอป Commerce และบล็อกเริ่มต้นของ Next.js เพื่อสร้างแอปเดโม 2 แอปที่ช่วยวัดผลกระทบของการใช้สคริปต์ของบุคคลที่สาม บุคคลที่สามที่ใช้กันโดยทั่วไปสําหรับ Google Tag Manager และการฝังโซเชียลมีเดียจะรวมอยู่ในหน้าแอปเหล่านี้โดยตรงในตอนแรก จากนั้นจึงรวมผ่านคอมโพเนนต์สคริปต์ จากนั้นเราเปรียบเทียบประสิทธิภาพของหน้าเว็บเหล่านี้ใน WebPageTest

สคริปต์ของบุคคลที่สามในแอปคอมเมิร์ซ Next.js

มีการเพิ่มสคริปต์ของบุคคลที่สามลงในเทมเพลตแอป Commerce สำหรับการสาธิตตามที่ระบุไว้ด้านล่าง

ก่อน หลัง
Google Tag Manager แบบแอซิงค์ คอมโพเนนต์สคริปต์ที่มีกลยุทธ์ = AfterInteractive สำหรับสคริปต์ทั้งสอง
ปุ่มติดตามของ Twitter ที่ไม่มีการทำงานแบบแอซิงค์หรือเลื่อน
การกําหนดค่าสคริปต์และคอมโพเนนต์สคริปต์สําหรับการสาธิต 1 ที่มีสคริปต์ 2 รายการ

การเปรียบเทียบต่อไปนี้แสดงความคืบหน้าของภาพสำหรับชุดเริ่มต้นใช้งาน Next.js Commerce ทั้ง 2 เวอร์ชัน ดังที่เห็น LCP เกิดขึ้นเร็วขึ้นเกือบ 1 วินาทีเมื่อเปิดใช้คอมโพเนนต์สคริปต์ด้วยกลยุทธ์การโหลดที่เหมาะสม

การเปรียบเทียบภาพสไลด์ที่แสดงการปรับปรุง LCP

สคริปต์ของบุคคลที่สามในบล็อก Next.js

เพิ่มสคริปต์ของบุคคลที่สามลงในแอปบล็อกเดโมตามที่ระบุไว้ด้านล่าง

ก่อน หลัง
Google Tag Manager แบบแอซิงค์ คอมโพเนนต์สคริปต์ที่มี strategy = lazyonload สําหรับสคริปต์แต่ละรายการ 4 รายการ
ปุ่มติดตามของ Twitter แบบแอซิงค์
ปุ่มติดตามของ YouTube แบบไม่ใช้ Async หรือเลื่อน
ปุ่มติดตามของ LinkedIn ที่ไม่มีการทำงานแบบแอซิงค์หรือเลื่อน
การกําหนดค่าสคริปต์และคอมโพเนนต์สคริปต์สําหรับการสาธิต 2 ที่มีสคริปต์ 4 รายการ
วิดีโอแสดงความคืบหน้าในการโหลดหน้าดัชนีที่มีและไม่มีคอมโพเนนต์สคริปต์ FCP ดีขึ้น 0.5 วินาทีเมื่อใช้คอมโพเนนต์สคริปต์

ดังที่เห็นในวิดีโอ First Contentful Paint (FCP) เกิดขึ้นที่ 0.9 วินาทีในหน้าเว็บที่ไม่มีคอมโพเนนต์สคริปต์ และ 0.4 วินาทีในหน้าเว็บที่มีคอมโพเนนต์สคริปต์

การพัฒนาคอมโพเนนต์สคริปต์ในอนาคต

แม้ว่าตัวเลือกกลยุทธ์สำหรับ afterInteractive และ lazyOnload จะมอบการควบคุมที่สำคัญเกี่ยวกับสคริปต์ที่บล็อกการแสดงผล แต่เรายังสำรวจตัวเลือกอื่นๆ ที่จะช่วยเพิ่มประโยชน์ของคอมโพเนนต์สคริปต์ด้วย

การใช้ผู้ปฏิบัติงานเกี่ยวกับเว็บ

สามารถใช้ผู้ปฏิบัติงานบนเว็บเพื่อเรียกใช้สคริปต์อิสระบนเทรดพื้นหลังได้ ซึ่งจะช่วยให้เทรดหลักว่างมากขึ้นในการจัดการกับงานด้านอินเทอร์เฟซผู้ใช้และปรับปรุงประสิทธิภาพ Web Worker เหมาะอย่างยิ่งสำหรับการประมวลผล JavaScript แทนการประมวลผล UI ออกจากเธรดหลัก สคริปต์ที่ใช้สำหรับการสนับสนุนลูกค้าหรือการตลาด ซึ่งปกติแล้วจะไม่โต้ตอบกับ UI อาจเป็นตัวเลือกที่ดีสำหรับการเรียกใช้ในเธรดแบ็กกราวด์ คุณอาจใช้ไลบรารีของบุคคลที่สามที่มีน้ำหนักเบาอย่าง PartyTown เพื่อแยกสคริปต์ดังกล่าวไว้ในเว็บเวิร์กเกอร์

เมื่อติดตั้งใช้งานคอมโพเนนต์สคริปต์ Next.js ในปัจจุบัน เราขอแนะนำให้เลื่อนเวลาสคริปต์เหล่านี้ในเธรดหลักโดยตั้งค่ากลยุทธ์เป็น afterInteractive หรือ lazyOnload ในอนาคต เราขอแนะนําให้เปิดตัวตัวเลือกกลยุทธ์ใหม่ 'worker' ซึ่งจะช่วยให้ Next.js ใช้ PartyTown หรือโซลูชันที่กําหนดเองเพื่อเรียกใช้สคริปต์ใน Web Worker ได้ เรายินดีรับฟังความคิดเห็นจากนักพัฒนาแอปเกี่ยวกับ RFC นี้

การลด CLS

เนื้อหาที่ฝังของบุคคลที่สาม เช่น โฆษณา วิดีโอ หรือการฝังฟีดโซเชียลมีเดีย อาจทําให้เลย์เอาต์เปลี่ยนเมื่อโหลดแบบเลื่อนดู ซึ่งจะส่งผลต่อประสบการณ์ของผู้ใช้และเมตริก Cumulative Layout Shift (CLS) ของหน้าเว็บ CLS สามารถลดได้โดยระบุขนาดของคอนเทนเนอร์ที่จะโหลดการฝัง

ระบบอาจใช้คอมโพเนนต์สคริปต์เพื่อโหลดการฝังที่อาจทําให้เลย์เอาต์เปลี่ยน โดยเรากำลังพิจารณาที่จะเพิ่มประสิทธิภาพดังกล่าวเพื่อมอบตัวเลือกการกำหนดค่าที่จะช่วยลด CLS ซึ่งอาจอยู่ในคอมโพเนนต์สคริปต์เองหรือเป็นคอมโพเนนต์ที่ใช้ร่วมกันก็ได้

คอมโพเนนต์ Wrapper

โดยทั่วไป ไวยากรณ์และกลยุทธ์การโหลดสําหรับการรวมสคริปต์ของบุคคลที่สามยอดนิยม เช่น Google Analytics หรือ Google Tag Manager (GTM) จะเป็นแบบคงที่ รายการเหล่านี้สามารถรวมไว้ในคอมโพเนนต์ Wrapper แต่ละรายการสำหรับสคริปต์แต่ละประเภท นักพัฒนาแอปจะมีสิทธิ์เข้าถึงแอตทริบิวต์เฉพาะแอปพลิเคชันเพียงชุดเล็กๆ (เช่น รหัสติดตาม) คอมโพเนนต์ Wrapper จะช่วยนักพัฒนาแอปในด้านต่อไปนี้

  1. ช่วยให้ผู้ใช้แท็กสคริปต์ยอดนิยมได้ง่ายขึ้น
  2. ตรวจสอบว่าเฟรมเวิร์กใช้กลยุทธ์ที่ดีที่สุด

บทสรุป

โดยปกติแล้วสคริปต์ของบุคคลที่สามจะสร้างขึ้นเพื่อรวมฟีเจอร์ที่เฉพาะเจาะจงไว้ในเว็บไซต์ที่ใช้งาน เราขอแนะนำให้เลื่อนเวลาการเรียกใช้สคริปต์ที่ไม่สำคัญออกไป ซึ่งคอมโพเนนต์สคริปต์ Next.js จะดำเนินการโดยค่าเริ่มต้น นักพัฒนาแอปมั่นใจว่าสคริปต์ที่รวมไว้จะไม่ทำให้ฟังก์ชันการทำงานที่สำคัญล่าช้าลง เว้นแต่จะใช้กลยุทธ์ beforeInteractive อย่างชัดแจ้ง นักพัฒนาเฟรมเวิร์กยังพิจารณาสร้างฟีเจอร์เหล่านี้ในเฟรมเวิร์กอื่นๆ ได้ด้วย เช่นเดียวกับคอมโพเนนต์สคริปต์ Next.js เรากำลังสำรวจการนำคอมโพเนนต์ที่คล้ายกันมาใช้กับทีม Nuxt.js นอกจากนี้ เรายังหวังว่าจะปรับปรุงคอมโพเนนต์สคริปต์เพิ่มเติมเพื่อครอบคลุมกรณีการใช้งานอื่นๆ จากความคิดเห็นที่ได้รับ

บริการรับรองคำให้การ

ขอขอบคุณ Kara Erickson, Janicklas Ralph, Katie Hempenius, Philip Walton, Jeremy Wagner และ Addy Osmani สำหรับความคิดเห็นเกี่ยวกับโพสต์นี้