ככל שאנחנו יוצרים יותר אתרים שמסתמכים על JavaScript, לפעמים אנחנו משלמים על מה שאנחנו שולחים למטה בדרכים שלא תמיד קל לנו לראות. במאמר הזה נסביר למה קצת משמעת יכולה לעזור לכם אם אתם רוצים שהאתר ייטען במהירות ויהיה אינטראקטיבי במכשירים ניידים. העברת פחות JavaScript יכולה לצמצם את הזמן של העברת הנתונים ברשת, את הזמן של דחיסת הקוד ואת הזמן של ניתוח והידור ה-JavaScript.
רשת
כשרוב המפתחים חושבים על העלות של JavaScript, הם חושבים עליה במונחים של עלות ההורדה וההפעלה. ככל שהחיבור של המשתמש איטי יותר, כך זמן השליחה של עוד בייטים של JavaScript יגדל.
זו יכולה להיות בעיה, כי סוג החיבור בפועל לרשת של המשתמש עשוי להיות לא 3G, 4G או Wi-Fi. אתם יכולים להיות מחוברים לרשת Wi-Fi בקפה, אבל להתחבר לנקודה לשיתוף אינטרנט (Hotspot) סלולרית במהירויות 2G.
אתם יכולים להפחית את עלות העברת הנתונים ברשת של JavaScript באמצעות:
- שולחים רק את הקוד שהמשתמש צריך.
- צמצום קוד
- משתמשים ב-UglifyJS כדי למזער קוד ES5.
- משתמשים ב-babel-minify או ב-uglify-es כדי לבצע אופטימיזציה של קוד ES2015 ואילך.
- דחיסה
- הסרת קוד שלא בשימוש.
- בעזרת הכלי לכיסוי קוד ב-DevTools תוכלו לזהות הזדמנויות להסרת קוד או לטעינת קוד באופן עצל.
- כדי להימנע מתרגום של תכונות שכבר קיימות בדפדפנים מודרניים, כדאי להשתמש ב-babel-preset-env וב-browserlist. מפתחים מתקדמים עשויים לגלות שניתוח יסודי של חבילות ה-Webpack עוזר לזהות הזדמנויות לצמצום יחסי התלות הלא נחוצים.
- כדי להסיר קוד, אפשר להיעזר ב-tree-shaking, באופטימיזציות המתקדמות של Closure Compiler ובפלאגינים לחיתוך ספריות כמו lodash-babel-plugin או ContextReplacementPlugin של webpack לספריות כמו Moment.js.
- שמירת קוד במטמון כדי לצמצם את מספר הבקשות לרשת.
- כדאי להשתמש באחסון במטמון של HTTP כדי לוודא שהדפדפנים מאחסנים את התשובות במטמון בצורה יעילה. כדי להימנע מהעברת בייטים שלא השתנו, כדאי לקבוע את משך החיים האופטימלי לסקריפטים (max-age) ולספק אסימוני אימות (ETag).
- שימוש במטמון של קובץ שירות (service worker) יכול לשפר את עמידות הרשת של האפליקציה ולספק גישה מיידית לתכונות כמו מטמון הקוד של V8.
- כדאי להשתמש במטמון לטווח ארוך כדי שלא תצטרכו לאחזר מחדש משאבים שלא השתנו. אם משתמשים ב-Webpack, אפשר לעיין במאמר גיבוב של שמות קבצים.
ניתוח/הידור
אחרי ההורדה, אחד מהעלויות הכבדות של JavaScript הוא הזמן שנדרש למנוע JS לנתח/לעבד את הקוד הזה. ב-Chrome DevTools, הניתוח וההדרכה הם חלק מהזמן הצהוב 'כתיבה ב-Script' בחלונית 'ביצועים'.
בכרטיסיות 'מלמטה למעלה' ו'עץ קריאות' מוצגים זמני הניתוח/הקמפלקציה המדויקים:

אבל למה זה חשוב?
אם חלף זמן רב על ניתוח או הידור של קוד, יכול להיות שהמשתמשים יצטרכו להמתין זמן רב יותר עד שיוכלו לבצע פעולות באתר. ככל ששולחים יותר JavaScript, כך זמן הניתוח וההדרכה שלו ארוך יותר עד שהאתר הופך לאינטראקטיבי.
עיבוד JavaScript בדפדפן יקר יותר מבייטים לכל תמונה או גופן אינטרנט בגודל שווה – Tom Dale
בהשוואה ל-JavaScript, יש עלויות רבות הכרוכות בעיבוד תמונות בגודל זהה (עדיין צריך לפענח אותן!), אבל בממוצע, בציוד לנייד, סביר יותר ש-JS תשפיע לרעה על האינטראקטיביות של הדף.

כשאנחנו מדברים על איטיות של ניתוח וקמפלקציה, חשוב להביא בחשבון את ההקשר – אנחנו מדברים כאן על טלפונים ניידים ממוצעים. משתמשים ממוצעים יכולים להשתמש בטלפונים עם מעבדים מרכזיים ומעבדי GPU איטיים, ללא מטמון L2/L3 ואולי אפילו עם מגבלת זיכרון.
יכולות הרשת והיכולות של המכשיר לא תמיד תואמות. משתמש עם חיבור Fiber מדהים לא בהכרח מקבל את המעבד הטוב ביותר לניתוח ולבדיקה של JavaScript שנשלח למכשיר שלו. זה נכון גם להפך… חיבור רשת גרוע אבל מעבד מהיר במיוחד. – Kristofer Baxter, LinkedIn
בהמשך אפשר לראות את העלות של ניתוח של כ-1MB של JavaScript (פשוט) ללא דחיסה בחומרה ברמה נמוכה וברמה גבוהה. הזמן הנדרש לניתוח או לקמפלקוד ארוך פי 2 עד 5 בטלפונים המהירים ביותר בשוק בהשוואה לטלפונים ממוצעים.

מה קורה אם מדובר באתר בעולם האמיתי, כמו CNN.com?
ב-iPhone 8 מתקדם, ניתוח או הידור של ה-JS של CNN נמשכים כ-4 שניות, לעומת כ-13 שניות בטלפון ממוצע (Moto G4). הדבר יכול להשפיע באופן משמעותי על המהירות שבה משתמש יכול ליצור אינטראקציה מלאה עם האתר.

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

האם אנחנו באמת שולחים יותר מדי JavaScript? אולי :)
בעזרת HTTP Archive (כ-500,000 אתרים מובילים) כדי לנתח את המצב של JavaScript בניידים, אנחנו יכולים לראות של-50% מהאתרים נדרשות יותר מ-14 שניות כדי להפוך לאינטראקטיביים. האתרים האלה משקיעים עד 4 שניות רק בניתוח ובהידור של JS.
אם מביאים בחשבון את הזמן שנדרש לאחזור ולעיבוד של JavaScript ומשאבים אחרים, לא מפתיע שהמשתמשים צריכים להמתין זמן מה עד שהדפים יהיו מוכנים לשימוש. בהחלט אפשר לשפר את זה.
הסרת קוד JavaScript לא קריטי מהדפים יכולה לקצר את זמני ההעברה, את הניתוח וההדרכה שמתבצעים במעבד ואת יתרת הזיכרון הפוטנציאלית. כך תוכלו גם להפוך את הדפים לאינטראקטיביים מהר יותר.
זמן ביצוע
לא רק ניתוח וקומפילציה יכולים להיות יקרים. הפעלת JavaScript (הרצת קוד אחרי שהוא נותח או הופעל) היא אחת מהפעולות שצריכות להתרחש ב-thread הראשי. זמני ביצוע ארוכים יכולים גם להשפיע על המועד שבו משתמש יכול לבצע אינטראקציה עם האתר.
אם הסקריפט פועל במשך יותר מ-50 אלפיות השנייה, הזמן עד לפעילות מלאה מתעכב בכל משך הזמן שנדרש להורדה, להדרכה ולביצוע של ה-JS – Alex Russell
כדי לטפל בבעיה הזו, מומלץ לחלק את הקוד ב-JavaScript לקטעים קטנים כדי למנוע נעילה של ה-thread הראשי. כדאי לבדוק אם אפשר לצמצם את כמות העבודה שמתבצעת במהלך הביצוע.
עלויות אחרות
JavaScript יכול להשפיע על ביצועי הדף בדרכים נוספות:
- זיכרון. יכול להיות שדפים ייראו קטועים או יושהו לעיתים קרובות בגלל GC (אוסף אשפה). כשדפדפן משחרר זיכרון, ביצוע ה-JS מושהה. לכן, דפדפן שמבצע איסוף אשפה לעיתים קרובות יכול להשהות את הביצוע בתדירות גבוהה יותר ממה שאנחנו רוצים. כדי למנוע דליפות זיכרון והשהיות תכופות של GC, חשוב להימנע מתנודות חדות בדפים.
- במהלך זמן הריצה, קוד JavaScript ארוך יכול לחסום את השרשור הראשי ולגרום לדפים שלא מגיבים. חלוקת העבודה לחלקים קטנים יותר (באמצעות
requestAnimationFrame()
אוrequestIdleCallback()
לתזמון) יכולה לצמצם בעיות שקשורות למהירות התגובה, וכך לשפר את המדד מהירות התגובה לאינטראקציה באתר (INP).
דפוסים להפחתת עלות העברת JavaScript
כדי להאט את זמני הניתוח/הקמפלקציה ואת זמני ההעברה ברשת של JavaScript, יש דפוסים שיכולים לעזור, כמו חלוקה למקטעים מבוססי-נתיב או PRPL.
PRPL
PRPL (Push, Render, Pre-cache, Lazy-load) הוא תבנית שמבצעת אופטימיזציה לאינטראקטיביות באמצעות פיצול קוד ושימוש נרחב במטמון:
נציג לכם תמונה ויזואלית של ההשפעה האפשרית.
אנחנו מנתחים את זמן הטעינה של אתרים פופולריים לנייד ושל אפליקציות אינטרנט מתקדמות (PWA) באמצעות נתוני הקריאה בזמן הריצה של V8. כפי שאפשר לראות, זמן הניתוח (שמוצג בכתום) הוא חלק משמעותי מהזמן שהמשתמשים מבלים באתרים האלה:
Wego הוא אתר שמשתמש ב-PRPL, ומצליח לשמור על זמן ניתוח קצר למסלולים שלו, כך שהאתר הופך לאינטראקטיבי במהירות רבה. רבים מהאתרים האחרים שצוינו למעלה השתמשו בחלוקת קוד ובתקציבי ביצועים כדי לנסות להפחית את העלויות שלהם ב-JS.
אתחול פרוגרסיבי
באתרים רבים מבצעים אופטימיזציה של החשיפה של התוכן על חשבון האינטראקטיביות. כדי לקבל ציור ראשוני מהיר כשיש חבילות JavaScript גדולות, לפעמים המפתחים משתמשים ברינדור בצד השרת, ולאחר מכן 'משדרגים' אותו כדי לצרף מנהלי אירועים כשה-JavaScript נשלף סוף סוף.
חשוב לזכור שיש לכך עלויות משלה. 1) בדרך כלל שולחים תשובה גדולה יותר ב-HTML, שיכולה להשפיע על האינטראקטיביות שלנו. 2) יכול להיות שהמשתמש יהיה במצב שבו חצי מהחוויה לא תהיה אינטראקטיבית עד ש-JavaScript תסיים את העיבוד.
גישה טובה יותר עשויה להיות Bootstrapping הדרגתי. שליחת דף עם פונקציונליות מינימלית (הדף מורכב רק מ-HTML/JS/CSS הנדרשים למסלול הנוכחי). ככל שמגיעים יותר משאבים, האפליקציה יכולה לטעון אותם באיטרציה ולפתוח תכונות נוספות.

הקוד צריך להיטען בהתאם לחלק שמוצג במסך. דפוסים שיכולים לעזור להשיג זאת הם PRPL ו-Progressive Bootstrapping.
מסקנות
גודל ההעברה הוא קריטי לרשתות ברמה נמוכה. זמן הניתוח חשוב במכשירים עם מעבדים שמוגבלים ל-CPU. חשוב לשמור על ערכי ה-latency וה-throughput נמוכים.
צוותים שבחרו להשתמש בתקציבי ביצועים מחמירים הצליחו לצמצם את זמני ההעברה והניתוח/הקמפלור של JavaScript. מומלץ לקרוא את המאמר של Alex Russell בנושא Can You afford it?: תקציבי ביצועים באינטרנט בעולם האמיתי" לקבלת הנחיות לגבי תקציבים לנייד.

אם אתם מפתחים אתר שמטרגט מכשירים ניידים, כדאי לנסות לפתח אותו בחומרה שמייצגת את המכשירים האלה, לקצר את זמני הניתוח או הידור של JavaScript ולהשתמש בתקציב ביצועים כדי לוודא שהצוות שלכם יכול לעקוב אחרי העלויות של JavaScript.
מידע נוסף
- Chrome Dev Summit 2017 – שיטות מומלצות לטעינת תוכן
- ביצועים בזמן ההפעלה של JavaScript
- פתרון המשבר בביצועי האינטרנט – Nolan Lawson
- האם יש לכם אפשרות להרשות לעצמכם את זה? תקציבי ביצועים בעולם האמיתי — אלכס ראסל
- הערכה של מסגרות וספריות לאינטרנט – Kristofer Baxter
- התוצאות של Cloudflare מהניסוי עם Brotli לדחיסה (חשוב לזכור ש-Brotli דינמי באיכות גבוהה יותר עלול לעכב את הרינדור הראשוני של הדף, לכן צריך להעריך אותו בזהירות. במקום זאת, מומלץ לבצע דחיסה סטטית).
- Performance Futures – סאם סאקוני