שיפור מהירות העמוד

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

מנגנון טעינה קטן אינו מעיד על פונקציה קלה; מודדים את האינטראקציה כולה.

בלוקים של שירותים חיצוניים מחוברים לעמוד, ואחד מהם מדגיש עלות ביצועים גבוהה יותר.

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

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

ממפים גם סקריפטים שלא הוספתם ישירות

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

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

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

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

משווים בדיקות מבוקרות לפני שמייחסים את הבעיה

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

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

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

דוחות ישנים כוללים בדיקה בשם “Reduce the impact of third-party code”. התיעוד של Chrome מציין שהבדיקה העצמאית הועברה החל מ-Lighthouse 13. הסף הישן של 250 ms אינו תקציב ביצועים אוניברסלי, ושמות הבדיקות אינם בהכרח זהים בדוחות עכשוויים. בודקים את גרסת הדוח ומשלבים אבחון עדכני עם תיעוד הדפדפן.

בוחרים את הרגע המוקדם שבו הפונקציה באמת נחוצה

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

אסטרטגיה מתי היא מתאימה העלות או הסיכון שנותרו
הסרת האינטגרציה הצורך הסתיים או שהפונקציה כפולה לבדוק תהליכים שתלויים בה
defer צריך HTML מפוענח וסדר הרצה עדיין משתמש ב-thread הראשי
async אין תלות בסדר המסמך ההרצה עלולה לחפוף לעבודה חשובה
טעינה סמוך לאזור הנראה ההטמעה נחוצה רק בהמשך העמוד ההורדה עשויה להתחיל לפני הצורך
טעינה בעקבות פעולה מכוונת סרטון, מפה או צ'אט הם אופציונליים המבקר ממתין לאתחול לאחר ההפעלה
טעינה לאחר הסכמה מתאימה השירות המוגדר דורש הרשאה זו האישור יכול להפעיל עבודה רבה יחד

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

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

מחליפים הטמעות אופציונליות בתצוגה מקדימה נגישה

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

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

html
<div class="media-slot" id="media-slot">
  <button type="button" id="load-media">Load product video</button>
</div>
<p id="media-status" role="status"></p>
<style>
  .media-slot { aspect-ratio: 16 / 9; background: #edf2f7; }
  .media-slot iframe { width: 100%; height: 100%; border: 0; }
</style>
<script type="module">
  const button = document.querySelector('#load-media');
  const slot = document.querySelector('#media-slot');
  const status = document.querySelector('#media-status');
  button.addEventListener('click', () => {
    button.disabled = true;
    status.textContent = 'Loading video';
    const frame = document.createElement('iframe');
    frame.title = 'Product video';
    frame.src = 'https://example.com/embed/product-video';
    frame.allowFullscreen = true;
    frame.addEventListener('load', () => {
      status.textContent = 'Video frame loaded';
    });
    slot.replaceChildren(frame);
    frame.focus();
  }, { once: true });
</script>

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

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

טוענים את הצ'אט פעם אחת ומאפשרים התאוששות מכשל

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

js
let chatScriptPromise;

export function loadChatScript() {
  if (chatScriptPromise) return chatScriptPromise;
  chatScriptPromise = new Promise((resolve, reject) => {
    const script = document.createElement('script');
    script.src = 'https://example.com/widgets/chat.js';
    script.async = true;
    script.onload = () => resolve();
    script.onerror = () => {
      script.remove();
      chatScriptPromise = undefined;
      reject(new Error('Chat script could not be loaded'));
    };
    document.head.append(script);
  });
  return chatScriptPromise;
}

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

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

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

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

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

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

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

מונעים ממנהל התגיות להפוך לאפליקציה נוספת

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

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

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

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

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

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

לכל אינטגרציה חדשה מגדירים בעלות ודרך יציאה

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

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

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

מדריכים קשורים