חבילת Next.js לניהול ספריות של צד שלישי

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

בפוסט הזה בבלוג נספק סקירה כללית של התכונות החדשות שפרסמנו, במיוחד הספרייה @next/third-parties, וכן סקירה כללית של יוזמות עתידיות בתוכנית העבודה שלנו.

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

41% מכל הבקשות של צד שלישי באתרים של Next.js הן סקריפטים. בניגוד לסוגי תוכן אחרים, הורדה והפעלה של סקריפטים יכולות להימשך זמן רב, מה שעלול לחסום את העיבוד ולהשהות את האינטראקציה של המשתמשים. נתונים מדוח חוויית המשתמש ב-Chrome‏ (CrUX) מראים שבאתרים של Next.js שמטעינים יותר סקריפטים של צד שלישי, שיעורי הצלחה של אינטראקציה לאינטראקציה הבאה (INP) ושל המהירות שבה נטען רכיב התוכן הכי גדול (LCP) נמוכים יותר.

תרשים עמודות שבו מוצג ירידה באחוז הנכסים ב-Next.js שהשיגו ציונים טובים במדדי INP ו-LCP, בהתאם למספר הצדדים השלישיים שנטענו
דוח CrUX של דצמבר 2023 (110,823 אתרים)

המתאם שנצפה בתרשים הזה לא מעיד על קשר סיבתי. עם זאת, ניסויים מקומיים מספקים הוכחה נוספת לכך שסקריפטים של צד שלישי משפיעים באופן משמעותי על ביצועי הדף. לדוגמה, התרשים הבא משווה בין מדדים שונים של Labs כשמאגר של Google Tag Manager – שכולל 18 תגים שנבחרו באופן אקראי – נוסף ל-Taxonomy, אפליקציית Next.js לדוגמה.

תרשים עמודות שבו מוצג ההבדל בין מדדים שונים של מעבדה כשאתר נטען עם Google Tag Manager וללא Google Tag Manager
WebPageTest (Mobile 4G - Virginia USA)

בתיעוד של WebPageTest מוסבר איך נמדדים הזמנים האלה. כבר במבט מהיר אפשר לראות שכל המדדים האלה ב-Lab מושפעים מהקונטיינר של GTM. לדוגמה, Total Blocking Time (TBT) – שרת proxy שימושי במעבדה שמשויך ל-INP – רשם עלייה של כמעט פי 20.

רכיב סקריפט

כשהשקנו את הרכיב <Script> ב-Next.js, הקפדנו להציג אותו באמצעות ממשק API ידידותי למשתמש שדומה מאוד לאלמנט <script> המסורתי. בעזרת היכולת הזו, מפתחים יכולים למקם סקריפט של צד שלישי בכל רכיב באפליקציה, ו-Next.js ידאג לסדר את הסקריפט אחרי שכל המשאבים הקריטיים ייטענו.

<!-- By default, script will load after page becomes interactive -->
<Script src="https://example.com/sample.js" />

<!-- Script is injected server-side and fetched before any page hydration occurs -->
<Script strategy=”beforeInteractive” src="https://example.com/sample.js" />

<!-- Script is fetched later during browser idle time -->
<Script strategy=”lazyOnload” src="https://example.com/sample.js" />

עשרות אלפי אפליקציות Next.js – כולל אתרים פופולריים כמו Patreon,‏ Target ו-Notion – משתמשות ברכיב <Script>. למרות היעילות שלו, חלק מהמפתחים הביעו חששות לגבי הנושאים הבאים:

  • איפה למקם את הרכיב <Script> באפליקציית Next.js תוך שמירה על ההוראות השונות להתקנה של ספקי צד שלישי שונים (חוויית המפתח).
  • אסטרטגיית הטעינה האופטימלית ביותר לשימוש בסקריפטים שונים של צד שלישי (חוויית משתמש).

כדי לטפל בשני החששות האלה, השקנו את @next/third-parties – ספרייה ייעודית שמציעה קבוצה של רכיבים ושירותים מנוהלים בהתאמה אישית לצדדים שלישיים פופולריים.

חוויית המפתח: ניהול קל יותר של ספריות של צד שלישי

בחלק גדול מהאתרים ב-Next.js נעשה שימוש בסקריפטים רבים של צד שלישי, כאשר Google Tag Manager הוא הפופולרי ביותר, ו66% מהאתרים משתמשים בו. @next/third-parties מבוסס על הרכיב <Script>, ומציג חבילות ברמה גבוהה יותר שנועדו לפשט את השימוש בתרחישי השימוש הנפוצים האלה.

import { GoogleAnalytics } from "@next/third-parties/google";

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
      <GoogleTagManager gtmId="GTM-XYZ" />
    </html>
  );
}

ל-Google Analytics – סקריפט נוסף של צד שלישי שנמצא בשימוש נרחב (52% מהאתרים ב-Next.js) – יש גם רכיב ייעודי משלו.

import { GoogleAnalytics } from "@next/third-parties/google";

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
      <GoogleAnalytics gaId="G-XYZ" />
    </html>
  );
}

@next/third-parties מפשט את תהליך הטעינה של סקריפטים נפוצים, אבל הוא גם מרחיב את היכולת שלנו לפתח כלי עזר לקטגוריות אחרות של צדדים שלישיים, כמו הטמעות. לדוגמה, 8% ו-4% מהאתרים ב-Next.js כוללים הטמעות של מפות Google ו-YouTube, וגם שלחנו רכיבים שיעזרו לכם לטעון אותם בקלות רבה יותר.

import { GoogleMapsEmbed } from "@next/third-parties/google";
import { YouTubeEmbed } from "@next/third-parties/google";

export default function Page() {
  return (
    <>
      <GoogleMapsEmbed
        apiKey="XYZ"
        height={200}
        width="100%"
        mode="place"
        q="Brooklyn+Bridge,New+York,NY"
      />
      <YouTubeEmbed videoid="ogfYd705cRs" height={400} params="controls=0" />
    </>
  );
}

חוויית משתמש: טעינה מהירה יותר של ספריות של צד שלישי

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

לדוגמה, תוכלו להטמיע סרטונים מ-YouTube. במקרים שבהם יש הטמעות חלופיות עם ביצועים טובים בהרבה מההטמעה המובנית. נכון לעכשיו, הרכיב <YouTubeEmbed> שיוצא על ידי @next/third-parties משתמש ב-lite-youtube-embed, שמטען מהר יותר בהשוואה ל-"Hello, World" ב-Next.js.

קובץ GIF שבו מוצגת השוואה בין זמן הטעינה של דף עם רכיב הטמעה של YouTube לבין זמן הטעינה של דף עם iframe רגיל של YouTube
WebPageTest (Mobile 4G - Virginia USA)

באופן דומה, במפות Google אנחנו כוללים את loading="lazy" בתור מאפיין ברירת המחדל להטמעה, כדי לוודא שהמפה נטענת רק כשהיא במרחק מסוים מחלון התצוגה. יכול להיות שזה נראה כמו מאפיין ברור שצריך לכלול – במיוחד מכיוון שהמסמכים של מפות Google כוללים אותו בקטע הקוד לדוגמה – אבל רק 45% מהאתרים ב-Next.js שמטמיעים את מפות Google משתמשים ב-loading="lazy".

הפעלת סקריפטים של צד שלישי ב-web worker

אחת מהשיטות המתקדמות שאנחנו בודקים ב-@next/third-parties היא הפחתת העומס על הסקריפטים של הצד השלישי באמצעות Web Worker. השיטה הזו, שפופולרית בספריות כמו Partytown, יכולה להפחית באופן משמעותי את ההשפעה של סקריפטים של צד שלישי על ביצועי הדף על ידי העברה שלהם לגמרי מהשרשור הראשי.

בקובץ ה-GIF הבא מוצגים השינויים במשך הזמן של משימות ארוכות ובזמן החסימה של הליבה כשמחילים אסטרטגיות שונות של <Script> על מאגר GTM באתר Next.js. חשוב לזכור שהחלפת האפשרויות של האסטרטגיה רק מעכבת את מועד ההפעלה של הסקריפטים האלה, אבל העברה שלהם ל-web worker מבטלת לחלוטין את הזמן שהם נמצאים בשרשור הראשי.

קובץ GIF שבו מוצגים ההבדלים בזמן החסימה של הליבה של האסטרטגיות השונות של סקריפטים
WebPageTest (Mobile 4G - Virginia USA)

בדוגמה הספציפית הזו, העברת הביצוע של מאגר התגים ב-GTM והסקריפטים של התגים המשויכים אליו ל-web worker צמצמה את זמן הטעינה של הדף ב-92%.

חשוב לציין שאם לא מנהלים את הטכניקה הזו בזהירות, היא עלולה לגרום לשיבושים שקטים בסקריפטים רבים של צד שלישי, וכך להקשות על ניפוי הבאגים. בחודשים הקרובים נבדוק אם רכיבי צד שלישי שמוצעים על ידי @next/third-parties פועלים בצורה תקינה כשהם מופעלים ב-web worker. אם כן, נעבוד על מתן דרך קלה ואופציונלית למפתחים להשתמש בשיטה הזו.

השלבים הבאים

בתהליך הפיתוח של החבילה הזו, התברר שיש צורך לרכז את ההמלצות בנוגע לטעינת צד שלישי, כדי שגם מסגרות אחרות יוכלו ליהנות מאותן שיטות בסיסיות. לכן פיתחנו את Third Party Capital, ספרייה שמשתמשת ב-JSON כדי לתאר שיטות טעינה של צד שלישי, וכיום היא משמשת כבסיס ל-@next/third-parties.

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

אם אחד מהשירותים של הצד השלישי שבהם אתם משתמשים באפליקציית Next.js נתמך על ידי @next/third-parties, תוכלו להתקין את החבילה ולנסות אותה. נשמח לקבל ממך משוב ב-GitHub.