סקריפטים של צד שלישי משפיעים על הביצועים, לכן חשוב לבדוק אותם באופן קבוע ולהשתמש בשיטות יעילות לטעינתם. בשיעור הזה תלמדו איך לבצע אופטימיזציה של טעינת המשאבים של צד שלישי. הוא כולל את השיטות הבאות:
דחיית טעינה של סקריפט
טעינה מדורגת של משאבים לא קריטיים
קישור מראש למקורות נדרשים
באפליקציית הדוגמה שכלולה בערכה יש דף אינטרנט פשוט עם שלוש תכונות שמגיעות ממקורות של צד שלישי:
הטמעת סרטון
ספריית ויזואליזציה של נתונים לעיבוד תרשים קו
ווידג'ט לשיתוף ברשתות חברתיות
נתחיל במדידת הביצועים של האפליקציה, ולאחר מכן ניישם כל אחת מהשיטות כדי לשפר היבטים שונים של ביצועי האפליקציה.
מדידת ביצועים
קודם פותחים את אפליקציית הדוגמה בתצוגת מסך מלא:
- לוחצים על Remix to Edit כדי לאפשר עריכה של הפרויקט.
- כדי לראות תצוגה מקדימה של האתר, לוחצים על הצגת האפליקציה. לאחר מכן לוחצים על מסך מלא .
מריצים בדיקת ביצועים של Lighthouse בדף כדי לקבוע את רמת הביצועים הבסיסית:
- מקישים על Control+Shift+J (או על Command+Option+J ב-Mac) כדי לפתוח את DevTools.
- לוחצים על הכרטיסייה Lighthouse.
- לוחצים על נייד.
- מסמנים את התיבה ביצועים. (אפשר לבטל את הסימון של שאר התיבות בקטע 'ביקורות').
- לוחצים על הדמיה של 3G מהיר, האטה פי 4 במהירות התגובה של יחידת העיבוד המרכזית (CPU).
- מסמנים את התיבה Clear Storage.
- לוחצים על הרצת ביקורות.
כשמריצים ביקורת במחשב, התוצאות המדויקות עשויות להשתנות, אבל כדאי לשים לב שהזמן של הצגת התוכן הראשוני (FCP) ארוך למדי, ושהכלי Lighthouse מציע שתי הזדמנויות לבדיקה: הסרת משאבים שחוסמים את העיבוד והתחברות מראש למקורות הנדרשים. (גם אם כל המדדים בירוק, עדיין אפשר לשפר את הביצועים באמצעות אופטימיזציה).
דחיית JavaScript של צד שלישי
בבדיקה הסרת משאבים שחוסמים עיבוד זוהתה אפשרות לחסוך זמן על ידי דחיית סקריפט שמגיע מ-d3js.org:
D3.js היא ספריית JavaScript ליצירת תצוגות חזותיות של נתונים. בקובץ script.js
באפליקציית הדוגמה נעשה שימוש בפונקציות השירות של D3 כדי ליצור את תרשים הקו של ה-SVG ולהוסיף אותו לדף. חשוב לשים לב לסדר הפעולות: הפונקציה script.js
צריכה לפעול אחרי שמנתחים את המסמך ושהספרייה D3 נטענת, ולכן היא כלולה ממש לפני התג </body>
הסגור ב-index.html
.
עם זאת, סקריפט D3 נכלל ב-<head>
של הדף, שחוסם את הניתוח של שאר המסמך:
שני מאפיינים קסומים יכולים לבטל את החסימה של המנתח כשהם מתווספים לתג הסקריפט:
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
מופעלים לפי הסדר שבו הם צוינו. כדי לוודא ש-script.js
יופעל אחרי ש-D3 יהיה מוכן, מוסיפים לו את defer
ומעבירים אותו אל <head>
של המסמך, ממש אחרי הרכיב <script>
של D3. עכשיו הוא לא חוסם יותר את המנתח, וההורדה מתחילה מוקדם יותר.
<script src="https://d3js.org/d3.v3.min.js" defer></script>
<script src="./script.js" defer></script>
טעינה מדורגת של משאבים של צד שלישי
כל המשאבים שמופיעים בחלק הנגלל הם מועמדים טובים לטעינה איטית.
באפליקציית הדוגמה יש סרטון YouTube שמוטמע ב-iframe. כדי לבדוק כמה בקשות הדף שולח ואילו בקשות מגיעות מה-iframe המוטמע של YouTube:
- כדי לראות תצוגה מקדימה של האתר, לוחצים על הצגת האפליקציה. לאחר מכן לוחצים על מסך מלא .
- מקישים על Control+Shift+J (או על Command+Option+J ב-Mac) כדי לפתוח את DevTools.
- לוחצים על הכרטיסייה רשתות.
- מסמנים את התיבה Disable cache (השבתת המטמון).
- בתפריט הנפתח Throttling, בוחרים באפשרות Fast 3G.
- טוענים מחדש את הדף.
בחלונית Network (רשת) מוצג שהדף שלח סה"כ 28 בקשות והעביר כמעט 1MB של משאבים דחוסים.
כדי לזהות את הבקשות שהוגשו על ידי iframe
של YouTube, מחפשים את מזהה הווידאו 6lfaiXM6waw
בעמודה הגורם שהתחיל את התהליך. כדי לקבץ את כל הבקשות לפי דומיין:
בחלונית Network, לוחצים לחיצה ימנית על כותרת עמודה.
בתפריט הנפתח, בוחרים בעמודה Domains (דומיינים).
כדי למיין את הבקשות לפי דומיין, לוחצים על כותרת העמודה Domains.
המיון החדש מראה שיש בקשות נוספות לדומיינים של Google. בסך הכול, ה-iframe של YouTube שולח 14 בקשות לסקריפטים, לטבלאות סגנונות, לתמונות ולגופנים. אבל אם המשתמשים לא גוללים למטה כדי להפעיל את הסרטון, הם לא באמת זקוקים לכל הנכסים האלה.
אם תחכו לטעינת הסרטון באיטרציה עד שהמשתמש יגלול למטה לקטע הזה בדף, תוכלו לצמצם את מספר הבקשות שהדף שולח בהתחלה. הגישה הזו שומרת את נתוני המשתמשים ומאיצה את הטעינה הראשונית.
אחת מהדרכים להטמיע טעינת נתונים בזמן אמת היא באמצעות Intersection Observer, ממשק API לדפדפן שמתריע כשרכיב נכנס או יוצא מחלון התצוגה של הדפדפן.
שלב 1: מונעים את טעינת הסרטון בשלב הראשון
כדי לטעון באיטרציה את ה-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 כדי לטעון את הסרטון באיטרציה
כדי לטעון את הסרטון כשהמשתמש גולל אליו, צריך לדעת מתי זה קורה. כאן נכנס לתמונה Intersection Observer API. באמצעות Intersection Observer API אפשר לרשום פונקציית קריאה חוזרת שתתבצע בכל פעם שרכיב שאחריו רוצים לעקוב נכנס או יוצא מחלון התצוגה.
כדי להתחיל, יוצרים קובץ חדש ומעניקים לו את השם lazy-load.js
:
- לוחצים על קובץ חדש ומעניקים לו שם.
- לוחצים על הוספת הקובץ הזה.
מוסיפים את תג הסקריפט לחלק העליון של המסמך:
<script src="/lazy-load.js" defer></script>
ב-lazy-load.js
, יוצרים IntersectionObserver
חדש ומעבירים לו פונקציית קריאה חוזרת להרצה:
// 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);
});
});
- כדי לראות תצוגה מקדימה של האתר, לוחצים על הצגת האפליקציה. לאחר מכן לוחצים על מסך מלא .
- מקישים על Control+Shift+J (או על Command+Option+J ב-Mac) כדי לפתוח את DevTools.
- לוחצים על הכרטיסייה מסוף.
כדאי לנסות לגלול למעלה ולמטה. הערך של 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 בקשות ורק 260KB. זה שיפור משמעותי!
עכשיו גוללים למטה בדף ומעיינים בחלונית Network. כשמגיעים לסרטון, הדף אמור לגרום ליצירת בקשות נוספות.
קישור מראש למקורות נדרשים
דחיתם את הטעינה של קוד JavaScript לא קריטי והפעלתם טעינה איטית של הבקשות ל-YouTube. עכשיו הגיע הזמן לבצע אופטימיזציה של התוכן הנותר של הצד השלישי.
הוספת המאפיין rel=preconnect
לקישור מורה לדפדפן ליצור חיבור לדומיין לפני שליחת הבקשה למשאב הזה. מומלץ להשתמש במאפיין הזה במקורות שמספקים משאבים שאתם בטוחים שהדף זקוק להם.
בבדיקת Lighthouse שביצעתם בשלב הראשון, בקטע יצירת קישור מראש למקורות נדרשים, הוצע לכם לחסוך כ-400 אלפיות השנייה על ידי יצירת חיבורים מוקדמים לכתובות staticxx.facebook.com ו-youtube.com:
מכיוון שסרטון YouTube נטען עכשיו באיטרציה, נשאר רק staticxx.facebook.com, המקור של הווידג'ט לשיתוף ברשתות החברתיות. כדי ליצור חיבור מוקדם לדומיין הזה, פשוט מוסיפים תג <link>
ל-<head>
של המסמך:
<link rel="preconnect" href="https://staticxx.facebook.com">
הערכה מחדש של הביצועים
זהו המצב של הדף אחרי האופטימיזציה. כדי להריץ ביקורת נוספת של Lighthouse, פועלים לפי השלבים בקטע מדידת הביצועים ב-codelab.