ביצועי אתרים בקלות – מהדורת Google I/O 2018

בכנס Google IO 2018 הצגנו אוסף של כלים, ספריות ושיטות אופטימיזציה שמאפשרים לשפר בקלות את הביצועים באינטרנט. כאן אנחנו מסבירים אותם באמצעות האפליקציה The Oodles Theater. אנחנו גם מדברים על הניסויים שלנו עם טעינה חזויה ועל יוזמת Guess.js החדשה.

Ewa Gasperowicz

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

הצורך בביצועים

האינטרנט הופך לכבד יותר ויותר מדי שנה. אם נבדוק את מצב האינטרנט, נראה שדף חציוני בנייד שוקל כ-1.5MB, ורוב המשקל הזה הוא JavaScript ותמונות.

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

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

פירמידת ההיררכיה של חוויית המשתמש
איור 1. עד כמה המהירות חשובה למשתמשים? (Speed Matters, Vol. 3)

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

‫Lighthouse – בסיס לתהליך עבודה לשיפור הביצועים

‫Lighthouse הוא חלק מכלי הפיתוח ל-Chrome שמאפשר לכם לבצע ביקורת באתר ולתת לכם רמזים איך לשפר אותו.

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

בדיקות חדשות של Lighthouse
איור 2. בדיקות חדשות של Lighthouse

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

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

דוח Lighthouse לאפליקציה Oodles
איור 3. דוח Lighthouse לאפליקציית Oodles

הביצועים הראשוניים של האפליקציה שלנו, כפי שהוצגו בדוח Lighthouse, היו די גרועים. ברשת 3G, המשתמש היה צריך לחכות 15 שניות עד להצגת התוכן העיקרי (FMP) או עד שהאפליקציה הפכה לאינטראקטיבית. ‫Lighthouse הדגיש המון בעיות באתר שלנו, וציון הביצועים הכולל של 23 שיקף בדיוק את זה.

משקל הדף היה בערך 3.4MB – היינו חייבים לצמצם אותו.

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

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

הסרת משאבים מיותרים

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

היתרונות של כיווץ קוד
איור 4. הקטנה ודחיסה של קובצי JavaScript ו-CSS

‫Lighthouse מדגיש את ההזדמנות הזו בבדיקה של CSS ו-JavaScript שלא עברו כיווץ. השתמשנו ב-webpack לתהליך ה-build, אז כדי להקטין את הקובץ פשוט השתמשנו ב-Uglify JS plugin.

הקטנה היא משימה נפוצה, כך שתוכלו למצוא פתרון מוכן לכל תהליך build שבו אתם משתמשים.

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

השתמשנו באירוח ב-Firebase כדי לארח את הקוד שלנו, ו-Firebase מאפשר gzipping כברירת מחדל, כך שמעצם העובדה שאירחנו את הקוד שלנו ב-CDN סביר, קיבלנו את זה בחינם.

למרות ש-gzip היא שיטת דחיסה פופולרית מאוד, גם מנגנונים אחרים כמו Zopfli ו-Brotli צוברים תאוצה. רוב הדפדפנים תומכים ב-Brotli, ואפשר להשתמש בקובץ בינארי כדי לדחוס מראש את הנכסים לפני ששולחים אותם לשרת.

שימוש במדיניות מטמון יעילה

השלב הבא שלנו היה לוודא שאנחנו לא שולחים משאבים פעמיים אם אין צורך בכך.

הבדיקה Inefficient cache policy ב-Lighthouse עזרה לנו להבין שאנחנו יכולים לבצע אופטימיזציה של אסטרטגיות השמירה במטמון כדי להשיג בדיוק את זה. הגדרנו בשרת כותרת תפוגה של max-age, כדי לוודא שבביקור חוזר המשתמש יוכל להשתמש שוב במשאבים שהוא הוריד בעבר.

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

הסרת קוד שלא בשימוש

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

רמת הכיסוי של הקוד בכלי הפיתוח
איור 5. בדיקת רמת הכיסוי של הקוד

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

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

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

‫Lighthouse זיהה את הבעיה הזו גם בבדיקה של כללי CSS שלא בשימוש. הוא הראה חיסכון פוטנציאלי של יותר מ-400KB. אז חזרנו לקוד שלנו והסרנו גם את החלק של JavaScript וגם את החלק של CSS מהספרייה הזו.

אם נסיר את מתאם ה-MVC, גודל הסגנונות שלנו ירד ל-10KB
איור 6. אם נסיר את מתאם ה-MVC, גודל הסגנונות שלנו ירד ל-10KB!

זה הקטין את חבילת ה-CSS שלנו פי 20, וזה די טוב בשביל קוד קטן באורך שתי שורות.

כמובן שזה שיפר את ציון הביצועים, וגם את מהירות ההגעה לפונקציונליות מלאה (TTI).

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

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

הכפתורים לא פועלים כי חסרה ספרייה
איור 7. רכיב אחד עדיין השתמש בספרייה שהוסרה

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

הימנעות ממטעני ייעודיים (payloads) עצומים ברשת

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

בעזרת הביקורת Enormous network payload, ‏Lighthouse זיהה בעיה בחלק מהמטענים הייעודיים (payloads) ברשת.

זיהוי עומסים עצומים ברשת
איור 8. זיהוי עומסי נתונים עצומים ברשת

כאן ראינו שיש לנו קוד בנפח של יותר מ-3MB שנשלח – וזה די הרבה, במיוחד בנייד.

בראש הרשימה, Lighthouse הדגיש שיש לנו חבילת JavaScript של ספק עם 2MB של קוד לא דחוס. זו גם בעיה ש-webpack מדגיש.

כמו שאומרים: הבקשה הכי מהירה היא זו שלא נשלחת.

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

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

בדיקת חבילות JavaScript
איור 9. ביקורת על חבילות JavaScript

התחלנו עם webpack bundle analyzer, שהודיע לנו שאנחנו כוללים תלות שנקראת unicode, שהייתה 1.6MB של JavaScript מנותח, אז די הרבה.

אחר כך עברנו לעורך שלנו, ובאמצעות הפלאגין Import Cost ל-Visual code יכולנו לראות את העלות של כל מודול שייבאנו. כך גילינו איזה רכיב כלל קוד שהפנה למודול הזה.

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

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

ראינו שיפור כולל של 65% אחרי שהבאנו בחשבון את הגודל של החבילות האלה אחרי כיווץ ב-gzip וצמצום. וגילינו שזה באמת תהליך שכדאי לעשות.

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

קיצור זמן ההפעלה של JavaScript באמצעות פיצול קוד

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

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

ככה הדפדפן מעבד את JavaScript.

עיבוד JavaScript
איור 10. עיבוד JavaScript

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

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

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

זמן האתחול של JavaScript
איור 11. בדיקת זמן האתחול של JavaScript

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

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

פיצול קוד הוא כמו פיצה

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

אפשר להחיל פיצול קוד ברמת הנתיב או ברמת הרכיב. הוא עובד מצוין עם React ו-React Loadable,‏ Vue.js,‏ Angular,‏ Polymer,‏ Preact ועוד כמה ספריות.

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

פיצול קוד עם ייבוא דינמי
איור 13. פיצול קוד עם ייבוא דינמי

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

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

כדאי לנצל קונספטים כמו פיצול קוד, לבחון רעיונות כמו tree shaking ולעיין במאגר webpack-libs-optimizations כדי לקבל כמה רעיונות לצמצום גודל הספרייה אם אתם משתמשים ב-webpack.

בצע אופטימיזציה לתמונות

בדיחה על ביצועי טעינת תמונות

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

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

בדיקות של תמונות
איור 14. בדיקות תמונות ב-Lighthouse

התחלנו באופטימיזציה של התמונות.

לסבב אופטימיזציה חד-פעמי, אפשר להשתמש בכלים חזותיים כמו ImageOptim או XNConvert.

גישה אוטומטית יותר היא להוסיף שלב של אופטימיזציית תמונות לתהליך ה-build, באמצעות ספריות כמו imagemin.

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

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

לפני ואחרי אופטימיזציה
איור 15. לפני ואחרי אופטימיזציה

קובץ ה-PNG של הרקע סומן ב-webpack כגדול, ובצדק. אחרי ששינינו את הגודל שלו כך שיתאים לאזור התצוגה והרצנו אותו דרך ImageOptim, הגענו ל-100KB, שזה גודל קביל.

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

שימוש בפורמט הנכון לתוכן מונפש

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

באפליקציית Oodle, השתמשנו בקובץ GIF כרצף פתיחה בדף הבית. לפי Lighthouse, אנחנו יכולים לחסוך יותר מ-7MB אם נעבור לפורמט וידאו יעיל יותר. הקליפ שלנו שקל בערך 7.3MB, שזה הרבה יותר מדי לאתר סביר, אז במקום זאת הפכנו אותו לרכיב וידאו עם שני קובצי מקור – mp4 ו-WebM, כדי לתמוך ביותר דפדפנים.

החלפת קובצי GIF מונפשים בסרטון
איור 16. החלפת קובצי GIF מונפשים בסרטונים

השתמשנו בכלי FFmpeg כדי להמיר את קובץ ה-GIF המונפש לקובץ MP4. פורמט WebM מאפשר לכם לחסוך עוד יותר – ה-API של ImageOptim יכול לבצע המרה כזו בשבילכם.

ffmpeg -i animation.gif -b:v 0 -crf 40 -vf scale=600:-1 video.mp4

הצלחנו לחסוך יותר מ-80% מהמשקל הכולל שלנו בזכות ההמרה הזו. זה הקטין את הקובץ לכ-1MB.

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

הממשק הזה משתמש בערכים של זמן הלוך ושוב (RTT) ושל הורדה כדי להעריך את סוג הרשת שבה המשתמש משתמש. היא פשוט מחזירה מחרוזת, 2G איטי, 2G, ‏ 3G או 4G. אז בהתאם לערך הזה, אם המשתמש נמצא ברשת שהיא פחות מ-4G, אנחנו יכולים להחליף את רכיב הסרטון בתמונה.

if (navigator.connection.effectiveType) { ... }

זה קצת פוגע בחוויית השימוש, אבל לפחות אפשר להשתמש באתר בחיבור איטי.

טעינה מדורגת של תמונות מחוץ למסך

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

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

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

<!-- Import library -->
import lazysizes from 'lazysizes'  <!-- or -->
<script src="lazysizes.min.js"></script>

<!-- Use it -->

<img data-src="image.jpg" class="lazyload"/>
<img class="lazyload"
    data-sizes="auto"
    data-src="image2.jpg"
    data-srcset="image1.jpg 300w,
    image2.jpg 600w,
    image3.jpg 900w"/>

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

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

עזרה לדפדפן בהעברת משאבים קריטיים בשלב מוקדם

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

כיוצרי הדף, אנחנו יכולים להודיע לדפדפן מה באמת חשוב לנו. למרבה המזל, בשנתיים האחרונות ספקי הדפדפנים הוסיפו כמה תכונות שעוזרות לנו בכך, למשל רמזים למשאבים כמו link rel=preconnect, או preload או prefetch.

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

בואו נראה איך Lighthouse עוזר לנו להשתמש בחלק מהתכונות האלה בצורה יעילה.

הדבר הראשון ש-Lighthouse אומר לנו לעשות הוא להימנע מכמה נסיעות הלוך ושוב יקרות לכל מקור.

הימנעו מנסיעות הלוך ושוב מרובות ויקרות לכל מקור
איור 17. הימנעו מנסיעות הלוך ושוב מרובות ויקרות לכל מקור

באפליקציית Oodle, אנחנו משתמשים הרבה ב-Google Fonts. בכל פעם שאתם מוסיפים לדף גיליון סגנונות של Google Fonts, הוא מתחבר לעד שני תת-דומיינים. לפי Lighthouse, אם נצליח לחמם את החיבור הזה, נוכל לחסוך עד 300 אלפיות השנייה בזמן החיבור הראשוני.

באמצעות שימוש ב-link rel preconnect, אנחנו יכולים להסתיר ביעילות את זמן האחזור של החיבור.

זה יכול להשפיע מאוד, במיוחד במקרים כמו Google Fonts, שבהם ה-CSS של משפחת הגופנים מתארח ב-googleapis.com ומשאבי הגופנים מתארחים ב-Gstatic. אז הפעלנו את האופטימיזציה הזו וחסכנו כמה מאות אלפיות השנייה.

ההצעה הבאה של Lighthouse היא לטעון מראש בקשות חשובות.

טעינה מראש של בקשות חשובות
איור 18. טעינה מראש של בקשות חשובות

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

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

טעינה מראש של גופן אינטרנט נראית כך: מציינים את rel=preload, מעבירים את as עם סוג הגופן, ואז מציינים את סוג הגופן שמנסים לטעון, כמו woff2.

ההשפעה של זה על הדף שלכם יכולה להיות משמעותית מאוד.

ההשפעה של טעינה מראש של משאבים
איור 19. ההשפעה של טעינה מראש של משאבים

בדרך כלל, אם לא משתמשים ב-link rel preload, והגופנים לאינטרנט הם קריטיים לדף, הדפדפן צריך קודם כל לאחזר את ה-HTML, לנתח את ה-CSS, ורק בשלב הרבה יותר מאוחר הוא יאחזר את הגופנים לאינטרנט.

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

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

כתובות ה-URL של Google Fonts שאנחנו מציינים בגופנים שלנו בגיליונות הסגנונות הן משהו שצוות הגופנים מעדכן באופן די קבוע. כתובות ה-URL האלה יכולות לפוג או להתעדכן בתדירות קבועה, ולכן אם אתם רוצים שליטה מלאה על חוויית טעינת הגופנים, אנחנו ממליצים לארח בעצמכם את הגופנים לאינטרנט. זה יכול להיות נהדר כי זה נותן לכם גישה לדברים כמו link rel preload.

במקרה שלנו, הכלי Google Web Fonts Helper עזר לנו מאוד להעביר חלק מהגופנים האלה לאופליין ולהגדיר אותם באופן מקומי, אז כדאי לבדוק אותו.

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

תכונה ניסיונית: רמזים לגבי עדיפות

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

הגדרת עדיפות לתוכן שמוצג בהתחלה
איור 20. רמזים לגבי עדיפות

זו תכונה חדשה שמאפשרת לכם לרמוז לדפדפן עד כמה המשאב חשוב. היא חושפת מאפיין חדש – importance – עם הערכים low, ‏ high או auto.

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

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

הגדרת עדיפות לתוכן שמוצג בהתחלה
איור 21. הגדרת עדיפות לתוכן שמוצג בהתחלה

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

אנחנו מקווים להוסיף את התכונה הזו ל-Canary בעוד כמה שבועות, אז כדאי לעקוב אחרי העדכונים.

הגדירו אסטרטגיה לטעינת גופני אינטרנט

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

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

איך להימנע מטקסט בלתי נראה בזמן הטעינה של פונטים מסוג webfont
איור 22. הימנעות מטקסט בלתי נראה בזמן הטעינה של פונטים מסוג webfont

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

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

    @font-face {
      font-family: 'Montserrat';
      font-style: normal;
      font-display: swap;
      font-weight: 400;
      src: local('Montserrat Regular'), local('Montserrat-Regular'),
          /* Chrome 26+, Opera 23+, Firefox 39+ */
          url('montserrat-v12-latin-regular.woff2') format('woff2'),
            /* Chrome 6+, Firefox 3.6+, IE 9+, Safari 5.1+ */
          url('montserrat-v12-latin-regular.woff') format('woff');
    }

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

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

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

תוצאת תצוגת הגופן
איור 23. תוצאת תצוגת הגופן

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

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

הפחתת סקריפטים שחוסמים עיבוד

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

ברצועת ציר הזמן של Lighthouse אפשר לראות שבמהלך השניות הראשונות האלה, כשכל המשאבים נטענים, המשתמש לא ממש יכול לראות תוכן.

הזדמנות להפחית את מספר גיליונות הסגנונות שחוסמים רינדור
איור 24. הזדמנות לצמצם את מספר גיליונות הסגנונות שחוסמים רינדור

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

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

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

במקרה שלנו, השתמשנו במודול NPM שנקרא Critical כדי להטמיע את התוכן הקריטי ב-index.html במהלך שלב ה-build.

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

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

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

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

התוצאה

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

ציון הביצועים של Lighthouse עלה מ-23 ל-91. זו התקדמות די יפה מבחינת המהירות. כל השינויים בוצעו בעקבות בדיקה ומעקב רציפים אחרי דוח Lighthouse. אם אתם רוצים לבדוק איך הטמענו מבחינה טכנית את כל השיפורים, אתם מוזמנים לעיין במאגר שלנו, במיוחד בבקשות המיזוג (PR) שנוספו שם.

ביצועים חזויים – חוויות משתמש מבוססות-נתונים

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

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

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

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

איסוף נתונים מבוסס-נתונים לאפליקציות אינטרנט
איור 25. חבילות מבוססות-נתונים לאפליקציות אינטרנט

כדי להקל על הניסויים האלה, אנחנו שמחים להכריז על יוזמה חדשה שנקראת Guess.js.

Guess.js
איור 26. ‫Guess.js

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

כדאי לנסות את Guess.js ולספר לנו מה דעתכם.

סיכום

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

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

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

תודה מיוחדת ל: Ward Peeters, ‏ Minko Gechev, ‏ Kyle Mathews, ‏ Katie Hempenius, ‏ Dom Farolino,‏ Yoav Weiss, ‏ Susie Lu, ‏ Yusuke Utsunomiya, ‏ Tom Ankers, ‏ Lighthouse ו-דודל של Google.