טעינה דינמית: שיפור ביצועי האינטרנט במכשירים איטיים

איך מבצעים אופטימיזציה של האתרים בהתאם למגבלות ספציפיות של חומרה ורשתות כדי להבטיח לכל משתמש את החוויה הטובה ביותר?

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

בשיחה בנושא Chrome Dev וועידה, Addy Osmani מ-Google ונייט שלוס מ-Facebook מצאו פתרון לבעיה הזו – דפוס להצגת דפים שמתאימים יותר למגוון מגבלות משתמשים. הם קוראים לזה טעינה דינמית.

מהו טעינה דינמית?

טעינה דינמית כוללת העברת חוויות שונות למשתמשים שונים על סמך מגבלות הרשת והחומרה שלהם, ובפרט:

  • חוויית ליבה מהירה לכל המשתמשים (כולל במכשירים ברמה נמוכה).

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

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

  • הצגת תמונות וסרטונים באיכות נמוכה ברשתות איטיות.

  • הגבלת קצב הפריימים של אנימציות במכשירים בסיסיים.

  • הימנעות מפעולות שצורכות משאבים רבים מבחינה חישובית במכשירים ברמה נמוכה.

  • חסימת סקריפטים של צד שלישי במכשירים איטיים יותר.

  • טעינת JavaScript לא קריטי לאינטראקטיביות רק במעבדים (CPU) מהירים.

תמיכה בדפדפנים והטמעת טעינת דינמיקה

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

המאפיין navigator.deviceMemory משמש להפחתת צריכת הזיכרון במכשירים ברמה נמוכה.

תמיכה בדפדפנים

  • Chrome: 63.
  • Edge:‏ 79.
  • Firefox: לא נתמך.
  • Safari: לא נתמך.

מקור

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

תמיכה בדפדפן

  • Chrome: 37.
  • Edge:‏ 15.
  • Firefox: 48.
  • Safari: לא נתמך.

מקור

NetworkInformation.effectiveType

המאפיין navigator.connection.effectiveType משמש לשיפור העברת הנתונים כדי להשתמש בפחות רוחב פס.

תמיכה בדפדפנים

  • Chrome: 61.
  • Edge:‏ 79.
  • Firefox: לא נתמך.
  • Safari: לא נתמך.

מקור

NetworkInformation.saveData

הנכס navigator.connection.saveData משמש לניצול ההעדפות של המשתמש ב-Data Saver.

תמיכה בדפדפנים

  • Chrome: 49.
  • Edge:‏ ≤79.
  • Firefox: לא נתמך.
  • Safari: לא נתמך.

מקור

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

טעינה דינמית ב-React

React Adaptive Loading Hooks & Utilities הוא חבילת כלים לסביבת React שמאפשרת להתאים בקלות את האתרים למכשירים ברמה נמוכה יותר. היא כוללת:

  • ה-hook‏ useNetworkStatus() להתאמה על סמך סטטוס הרשת (slow-2g,‏ 2g,‏ 3g או 4g).

  • ה-hook‏ useSaveData() להתאמה על סמך ההעדפות של המשתמש ב'חיסכון בנתונים'.

  • ה-hook‏ useHardwareConcurrency() להתאמה על סמך מספר הליבות הלוגי של מעבד ה-CPU במכשיר של המשתמש.

  • ה-hook‏ useMemoryStatus() להתאמה על סמך זיכרון המכשיר (RAM) של המשתמש.

כל ה-hooks מקבלים ארגומנט אופציונלי להגדרת הערך הראשוני. האפשרות הזו שימושית בשני תרחישים: כשדפדפן המשתמש לא תומך ב-API הרלוונטי, וגם לצורך עיבוד בצד השרת, שבו אפשר להשתמש בנתוני ההנחיה של הלקוח כדי להגדיר את הערך הראשוני בשרת. לדוגמה, ההוק (hook) useNetworkStatus() יכול להשתמש בערך הראשוני שמועבר מרמז הלקוח לרינדור בצד השרת, וכשמריצים אותו על הלקוח הוא יכול לעדכן את עצמו אם סוג האפקטיביות ברשת משתנה.

ה-Hooks והכלים של React Adaptive Loading מיושמים באמצעות ממשקי API של פלטפורמות אינטרנט (Network Information,‏ Device Memory ו-Hardware Concurrency). אפשר להשתמש באותם ממשקי API כדי להחיל את העקרונות של טעינה דינמית על מסגרות וספריות אחרות, כמו Angular,‏ Vue ועוד.

טעינה דינמית בפעולה

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

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

ב-Twitter יש מצב לחיסכון בנתונים שנועד לצמצם את כמות הנתונים שבהם נעשה שימוש. במצב הזה, תמונות התצוגה המקדימה נטענות ברזולוציה נמוכה ותמונות גדולות נטענות רק כשמקישים על התצוגה המקדימה. כשהאפשרות הזו מופעלת, משתמשים ב-iOS וב-Android חוסכים 50% בשימוש בנתונים לצורך צפייה בתמונות, ומשתמשים באינטרנט חוסכים 80%. הנה דוגמה ל-React שמשתמשת ב-hook Save Data כדי ליצור רפליקות של ציר הזמן ב-Twitter. נסו לפתוח את החלונית Network של כלי הפיתוח ולבחון את ההבדל בין כמות הנתונים שמועברים בזמן הגלילה בזמן ש-Save Data מושבת לבין המצב שבו שמירת הנתונים מופעלת.

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

מערכת eBay מפעילה ומכבה תכונות מסוימות, כמו זום, באופן מותנה, אם התנאים של החומרה או הרשת של המשתמש לא תומכים בהן בצורה טובה. אפשר לעשות זאת באמצעות code-splitting וטעינת קוד באופן מותאם – דרך לטעון באופן מותנה רכיבים אינטראקטיביים יותר או להריץ פעולות חישוביות מורכבות יותר במכשירים מתקדמים, מבלי לשלוח את הסקריפטים למשתמשים במכשירים איטיים יותר. צפו בסרטון באורך 16 דקות שבו Addy מציג את הדפוס הזה שמוטמע באמצעות React.lazy() ו-Suspense, בדף המוצר להדגמה של eBay.

תרשים של מודולים שנשלחים לדף מוצר במכשירים ברמה נמוכה ובמכשירים ברמה גבוהה: שתי הגרסאות כוללות

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

צילום מסך של שתי גרסאות של צ'אט ב-Tinder: עם וידאו בהפעלה אוטומטית ועם וידאו עם שכבת-על של לחצן הפעלה. צילום מסך של פרופיל ב-Tinder עם הכיתוב 'הגבלת מספר התמונות בקרוסלה במצב חיסכון בנתונים או ב-3G'. קטע קוד להטמעת נתונים מראש של סרטונים בחלון התצוגה רק ב-4G.

טעינה דינמית ב-Facebook

אחת הבעיות שקשורות לטעינה אדפטיבית היא קיבוץ מכשירים לקבוצות של מכשירים מתקדמים ומכשירים בסיסיים על סמך האותות הזמינים. במכשירים ניידים, המחרוזת user-agent‏ (UA) מספקת את שם המכשיר, שמאפשר ל-Facebook להשתמש בנתונים שזמינים לכולם לגבי מאפייני המכשיר כדי לקבץ מכשירים ניידים לקבוצות. עם זאת, במחשבים, המידע הרלוונטי היחיד ב-UA הוא מערכת ההפעלה של המכשיר.

כדי לקבץ מכשירים למחשב, מערכת המעקב אחר הביצועים של Facebook מתעדת ביומן את הנתונים על מערכת ההפעלה, ליבות המעבד (מ-navigator.hardwareConcurrency) וזיכרון ה-RAM (navigator.deviceMemory). הם בחנו את היחסים בין סוגי חומרה שונים לביצועים, וסיווגו את המכשירים לחמש קטגוריות. שילוב של כיתות חומרה במעקב הביצועים מאפשר להם לקבל תמונה מלאה יותר של האופן שבו אנשים משתמשים במוצרי Facebook בהתאם למכשיר שלהם, ולזהות בקלות רבה יותר נסיגות בביצועים.

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

מידע נוסף על טעינה דינמית

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