אופטימיזציה של טעינת סקריפטים של צד שלישי ב-Next.js

להבין את החזון שמאחורי רכיב הסקריפט של Next.js, שמספק פתרון מובנה לביצוע אופטימיזציה של טעינת סקריפטים של צד שלישי.

Leena Sohoni
Leena Sohoni

כ-45% מהבקשות מאתרים בנייד ובמחשב הן בקשות של צד שלישי, ומתוכן 33% הן סקריפטים. הגודל, זמן האחזור והטעינה של סקריפטים של צד שלישי יכולים להשפיע באופן משמעותי על ביצועי האתר. רכיב הסקריפט Next.js מגיע עם שיטות מומלצות מובנות וברירות מחדל מובנות שנועדו לעזור למפתחים להוסיף סקריפטים של צד שלישי לאפליקציות שלהם, ובמקביל לטפל בבעיות ביצועים פוטנציאליות.

סקריפטים של צד שלישי וההשפעה שלהם על הביצועים

סקריפטים של צד שלישי מאפשרים למפתחי אתרים להשתמש בפתרונות קיימים כדי להטמיע תכונות נפוצות ולקצר את זמן הפיתוח. עם זאת, בדרך כלל אין ליוצרי הסקריפטים האלה תמריץ לבחון את ההשפעה על הביצועים של אתר שצורך אותו. גם הסקריפטים האלה משמשים כקופסה שחורה למפתחים שמשתמשים בהם.

סקריפטים אחראים למספר משמעותי של בייטים של צד שלישי שהורדו על ידי אתרים בקטגוריות שונות של בקשות של צד שלישי. כברירת מחדל, הדפדפן מתעדף סקריפטים על סמך המיקום שלהם במסמך, דבר שעלול לעכב את הגילוי או ההפעלה של סקריפטים שחיוניים לחוויית המשתמש.

כדי לעבד את הדף, צריך לטעון קודם ספריות של צד שלישי שנדרשות לפריסה. יש לדחות צדדים שלישיים שלא נדרשים לעיבוד הראשוני כדי שלא ייחסמו עיבוד אחר ב-thread הראשי. ב-Lighthouse יש שתי ביקורות לסימון סקריפטים חוסמים רינדור או חוסמי שרשור ראשי.

בדיקות Lighthouse כדי להסיר משאבים חוסמי עיבוד ולצמצם את השימוש בצדדים שלישיים

חשוב להתייחס לרצף של טעינת המשאבים בדף, כדי שלא יהיה עיכוב במשאבים קריטיים ושהמשאבים שאינם קריטיים לא יחסמו משאבים קריטיים.

יש שיטות מומלצות לצמצום ההשפעה של צדדים שלישיים, אבל לא כולם יודעים איך להטמיע את הפתרונות האלה בשביל כל צד שלישי שבו הם משתמשים. זה עשוי להיות מורכב מהסיבות הבאות:

  • בממוצע, אתרים משתמשים ב-21 עד 23 צדדים שלישיים שונים – כולל סקריפטים – בנייד ובמחשב. אופן השימוש וההמלצות עשויים להיות שונים בכל פלטפורמה.
  • ההטמעה של הרבה צדדים שלישיים עשויה להשתנות בהתאם לשימוש במסגרת מסוימת או בספרייה מסוימת של ממשק המשתמש.
  • אנחנו מוסיפים לעיתים קרובות ספריות חדשות יותר של צד שלישי.
  • מגוון דרישות עסקיות שקשורות לאותו צד שלישי מקשה על המפתחים לקבוע תקן אחד לשימוש באותו צד שלישי.

ההתמקדות של אורורה בסקריפטים של צד שלישי

חלק משיתוף הפעולה של Aurora עם מסגרות אינטרנט וכלים בקוד פתוח הוא מתן ברירות מחדל חזקות וכלים מקובעים כדי לעזור למפתחים לשפר היבטים של חוויית המשתמש, כמו ביצועים, נגישות, אבטחה ומוכנות לניידים. בשנת 2021 התמקדנו בשיפור של מקבצים של framework כדי לשפר את חוויית המשתמש ואת מדדי מדדי הליבה לבדיקת חוויית המשתמש באתר.

אחד מהשלבים המשמעותיים ביותר להשגת המטרה שלנו לשיפור הביצועים של framework הוא חיפוש של רצף הטעינה האידיאלי של סקריפטים של צד שלישי ב-Next.js. מסגרות כמו Next.js ממוקמות באופן ייחודי כדי לספק תכונות ברירת מחדל ותכונות שימושיות שעוזרות למפתחים לטעון משאבים ביעילות, כולל צדדים שלישיים. חקרנו מקיפים של HTTP Archive ונתונים של Lighthouse כדי למצוא את הצדדים השלישיים שיוצרים בלוקים מודעות בתדירות הגבוהה ביותר במסגרות שונות.

כדי לטפל בבעיה של חסימת סקריפטים של צד שלישי שחוסמים שרשור ראשי באפליקציה, פיתחנו את רכיב הסקריפט. הרכיב כולל תכונות יצירת רצף כדי לספק למפתחים אמצעי בקרה טובים יותר לטעינת סקריפטים של צד שלישי.

סדרת סקריפטים של צד שלישי ללא רכיב framework

ההנחיות הזמינות לצמצום ההשפעה של סקריפטים שחוסמים את העיבוד כוללות את השיטות הבאות לטעינה יעילה של סקריפטים של צד שלישי וסידור שלהם ברצף:

  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. טעינה מדורגת של משאבים והטמעות של צד שלישי אחרי שהתוכן של הדף הראשי הסתיים או כשהמשתמש גולל למטה לחלק בדף שבו הם נכללים.

רכיב הסקריפט Next.js

רכיב הסקריפט Next.js מיישם את השיטות שלמעלה לסידור סקריפטים ברצף, ומספק תבנית למפתחים להגדרת אסטרטגיית הטעינה שלהם. אחרי שתגדירו את האסטרטגיה המתאימה, היא תיטען באופן אופטימלי בלי לחסום משאבים קריטיים אחרים.

רכיב הסקריפט מבוסס על קוד ה-HTML <script> והוא מאפשר להגדיר את עדיפות הטעינה של סקריפטים של צד שלישי באמצעות מאפיין האסטרטגיה.

// 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" />

המאפיין 'אסטרטגיה' יכול לקבל שלושה ערכים.

  1. beforeInteractive: ניתן להשתמש באפשרות הזו לסקריפטים קריטיים שאמורים לפעול לפני שהדף הופך לאינטראקטיבי. Next.js מבטיח שסקריפטים כאלו יוחדרו ל-HTML הראשוני בשרת, ויבוצעו לפני JavaScript אחר באריזה עצמית. מומלץ להשתמש באסטרטגיה הזו לניהול הסכמה, סקריפטים לזיהוי בוטים או ספריות מסייעות שנדרשות לעיבוד תוכן ביקורתי.

  2. afterInteractive: זוהי שיטת ברירת המחדל שמוחלת, והיא זהה לטעינת סקריפט עם מאפיין העיכוב. צריך להשתמש בו לסקריפטים שהדפדפן יכול להריץ אחרי שהדף הוא אינטראקטיבי, לדוגמה, סקריפטים של Analytics. Next.js מחדיר את הסקריפטים האלה בצד הלקוח והם רצים אחרי טעינת הדף. לכן, אם לא צוין אחרת, כל הסקריפטים של צד שלישי שמוגדרים באמצעות רכיב הסקריפט נדחו על ידי Next.js, וכך הם מספקים ברירת מחדל חזקה.

  3. lazyOnload: ניתן להשתמש באפשרות הזו כדי לבצע טעינה מדורגת של סקריפטים בעדיפות נמוכה כשהדפדפן לא פעיל. הפונקציונליות שמסופקת על ידי סקריפטים כאלה לא נדרשת מיד לאחר שהדף הופך לאינטראקטיבי — לדוגמה, יישומי פלאגין של צ'אט או מדיה חברתית.

המפתחים יכולים לומר ל-Next.js איך האפליקציה שלהם משתמשת בסקריפט על ידי ציון האסטרטגיה. כך ה-framework יכול להחיל אופטימיזציות ושיטות מומלצות לטעינת הסקריפט, תוך שמירה על רצף הטעינה הטוב ביותר.

באמצעות רכיב הסקריפט, המפתחים יכולים למקם סקריפט של צד שלישי בכל מקום באפליקציה לצורך טעינה מאוחרת של צדדים שלישיים, וברמת המסמך עבור סקריפטים קריטיים. כלומר, ייתכן שרכיב הסקריפט ימוקם באופן משותף עם הרכיב באמצעות הסקריפט. לאחר שתיית הנוזלים, הסקריפט יוחדר לראש המסמך שעבר עיבוד, או לחלק התחתון של הגוף, בהתאם לשיטה שבה נעשה שימוש.

מדידת ההשפעה

השתמשנו בתבניות של אפליקציית המסחר של Next.js ושל הבלוג למתחילים כדי ליצור שתי אפליקציות להדגמה (דמו) שעזרו למדוד את ההשפעה של הוספת סקריפטים של צד שלישי. צדדים שלישיים נפוצים של Google Tag Manager והטמעות של רשתות חברתיות נכללו בדפים של האפליקציות האלה ישירות ולאחר מכן באמצעות רכיב הסקריפט. לאחר מכן השווינו בין הביצועים של הדפים האלה באתר WebPageTest.

סקריפטים של צד שלישי באפליקציית מסחר של Next.js

סקריפטים של צד שלישי נוספו לתבנית של אפליקציית המסחר האלקטרוני להדגמה (דמו), כפי שמוצג בהמשך.

לפני אחרי
Google Tag Manager עם אסינכרוני רכיב הסקריפט עם האסטרטגיה = afterInteractive לשני הסקריפטים
לחצן למעקב ב-Twitter ללא אסינכרוני או דחייה
הגדרה של רכיב הסקריפט והסקריפט להדגמה 1 עם 2 סקריפטים.

בהשוואה הבאה אפשר לראות את ההתקדמות החזותית בשתי הגרסאות של Next.js commerce- Kit. כמו שנראו, LCP מתרחש כמעט שנייה אחת קודם, כשרכיב הסקריפט הופעל עם אסטרטגיית הטעינה הנכונה.

השוואה בין רצועת השקפים שמציגה אימפרוביזציה של LCP

סקריפטים של צד שלישי בבלוג Next.js

סקריפטים של צד שלישי נוספו לאפליקציית הבלוג להדגמה, כפי שמפורט בהמשך.

לפני אחרי
Google Tag Manager עם אסינכרוני רכיב סקריפט עם אסטרטגיה = lazyonload לכל אחד מארבעת הסקריפטים
לחצן מעקב ב-Twitter עם אסינכרוני
לחצן ההרשמה ל-YouTube ללא אסינכרוני או דחייה
לחצן למעקב ב-LinkedIn ללא אסינכרוני או דחייה
הגדרה של רכיב הסקריפט והסקריפט להדגמה (דמו 2) עם 4 סקריפטים.
סרטון שמציג את התקדמות הטעינה של דף האינדקס, עם או בלי רכיב הסקריפט. יש שיפור של 0.5 שניות ב-FCP באמצעות רכיב הסקריפט.

כמו שאפשר לראות בסרטון, המהירות שבה נטען רכיב התוכן (FCP) מתרחשת בדף אחרי 0.9 שניות ללא רכיב הסקריפט, ו-0.4 שניות עם רכיב הסקריפט.

מה השלב הבא ברכיב הסקריפט

אפשרויות האסטרטגיה עבור afterInteractive ו-lazyOnload מספקות שליטה משמעותית בסקריפטים שחוסמים עיבוד, אבל אנחנו בודקים גם אפשרויות נוספות שיגדילו את התועלת של רכיב הסקריפט.

שימוש ב-Web worker

אפשר להשתמש ב-Web worker כדי להריץ סקריפטים עצמאיים על שרשורי רקע, וכך לפנות את ה-thread הראשי כדי לטפל במשימות של ממשק משתמש בעיבוד ולשפר את הביצועים. Web Workers מתאים במיוחד להסרת עיבוד JavaScript, ולא לעבודה בממשק המשתמש, מחוץ ל-thread הראשי. סקריפטים שמשמשים לתמיכת לקוחות או לשיווק, שבדרך כלל אין להם אינטראקציה עם ממשק המשתמש, יכולים להיות מועמדים טובים להפעלה בשרשור ברקע. ספרייה פשוטה של צד שלישי – PartyTown – עשויה לשמש לבידוד סקריפטים כאלה ותוביל אותם לעובדי אינטרנט.

בעקבות ההטמעה הנוכחית של רכיב הסקריפט Next.js, מומלץ לדחות את הסקריפטים ב-thread הראשי על ידי הגדרת האסטרטגיה ל-afterInteractive או ל-lazyOnload. בעתיד, אנחנו מציעים להוסיף אפשרות חדשה לאסטרטגיה 'worker', שתאפשר ל-Next.js להשתמש ב-PartyTown או בפתרון מותאם אישית להרצת סקריפטים על עובדי אינטרנט. אנחנו מקבלים בברכה תגובות ממפתחים ב-RFC הזה.

צמצום ה-CLS

הטמעות של צד שלישי, כמו מודעות, סרטונים או הטמעות של פידים של רשתות חברתיות, יכולות לגרום לשינויים בפריסה במהלך טעינה מדורגת. המצב הזה משפיע על חוויית המשתמש ועל המדד Cumulative Layout Shift (CLS) של הדף. אפשר למזער את ה-CLS באמצעות ציון גודל המאגר שבו ההטמעה תיטען.

אפשר להשתמש ברכיב הסקריפט כדי לטעון הטמעות שיכולות לגרום לשינויים בפריסה. אנחנו שוקלים להרחיב אותו כדי לספק אפשרויות הגדרה שיעזרו להפחית את ה-CLS. הוא יכול להיות זמין ברכיב הסקריפט עצמו או כרכיב נלווה.

רכיבי מעטפת

אסטרטגיית התחביר והטעינה להכללת סקריפטים פופולריים של צד שלישי, כמו Google Analytics או Google Tag Manager (GTM) בדרך כלל, היא קבועה. אפשר לכלול את הרכיבים האלה ברכיבי wrapper נפרדים לכל סוג של סקריפט. מפתחים יכולים להשתמש רק בקבוצה מינימלית של מאפיינים ספציפיים לאפליקציה (כמו מזהה לצורכי מעקב). רכיבי Wrapper יעזרו למפתחים על ידי:

  1. כדי להקל עליהם לכלול תגי סקריפטים פופולריים.
  2. יש לוודא שהמסגרת משתמשת באסטרטגיה האופטימלית ביותר.

סיכום

בדרך כלל סקריפטים של צד שלישי נוצרים כדי לכלול תכונות ספציפיות באתר הצורך. כדי לצמצם את ההשפעה של סקריפטים לא קריטיים, מומלץ לדחות אותם – פעולה שרכיב הסקריפט Next.js מבצע כברירת מחדל. המפתחים יכולים להיות בטוחים שסקריפטים מכילים סקריפטים לא יעכבו את הפונקציונליות הקריטית, אלא אם הם יחילו באופן מפורש את האסטרטגיה beforeInteractive. בדומה לרכיב הסקריפט Next.js, מפתחי framework יכולים גם לשקול לפתח את התכונות האלה ב-frameworks אחרות. אנחנו בודקים באופן פעיל את האפשרות להנחית רכיב דומה עם צוות Nuxt.js. על סמך המשוב, אנחנו מקווים גם לשפר את רכיב הסקריפט כך שיכלול תרחישים נוספים לדוגמה.

אימות חתימות

תודה לKara Erickson, Janicklas Ralph, Katie Hempenius, Philip Walton, Jeremy Wagner ו-Addy Osmani על המשוב שלהן לגבי הפוסט הזה.