סקריפטים של צד שלישי משפיעים על הביצועים, לכן חשוב לבדוק אותם באופן קבוע ולהשתמש בשיטות יעילות לטעינתם. בשיעור הזה תלמדו איך לבצע אופטימיזציה של טעינת משאבים של צד שלישי. הוא עוסק בשיטות הבאות:
דחיית טעינה של סקריפט
טעינה מדורגת של משאבים לא קריטיים
קישור מראש למקורות נדרשים
האפליקציה לדוגמה הכלולה באפליקציה כוללת דף אינטרנט פשוט עם שלוש תכונות שמגיעות ממקורות של צד שלישי:
הטמעת סרטון
ספריית ויזואליזציה של נתונים לעיבוד תרשים קו
ווידג'ט לשיתוף במדיה חברתית
נתחיל במדידת הביצועים של האפליקציה, ולאחר מכן ניישם כל אחת מהשיטות כדי לשפר היבטים שונים של ביצועי האפליקציה.
מדידת ביצועים
קודם פותחים את אפליקציית הדוגמה בתצוגת מסך מלא:
- לוחצים על 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. ממשק ה-API של Intersection Observer מאפשר לרשום פונקציית קריאה חוזרת שמופעלת בכל פעם שרכיב שרוצים לעקוב אחריו נכנס לאזור התצוגה או יוצא ממנו.
כדי להתחיל, יוצרים קובץ חדש ומעניקים לו את השם lazy-load.js
:
- לוחצים על קובץ חדש ומעניקים לו שם.
- לוחצים על Add This File (הוספת הקובץ הזה).
מוסיפים את תג הסקריפט לכותרת של המסמך:
<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: הערכה מחדש של הביצועים
כדי לראות איך השתנו הגודל ומספר המשאבים, פותחים את החלונית רשת בכלי הפיתוח וטוענים מחדש את הדף. בחלונית Network (רשת) מוצג שהדף שלח 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.