בכנס Google IO בשנת 2018 הצגנו סקירה של כלים, ספריות וטכניקות אופטימיזציה שמקלים על שיפור הביצועים של אתרים. במאמר הזה נסביר על הטכניקות האלה באמצעות האפליקציה The Oodles Theater. נספר גם על הניסויים שלנו בטעינה חיזויית ועל היוזמה החדשה Guess.js.
בשנה האחרונה היינו עסוקים מאוד בניסיון להבין איך להפוך את האינטרנט למהיר יותר ולשפר את הביצועים שלו. הדבר הוביל ליצירת כלים, גישות וספריות חדשים שאנחנו רוצים לשתף איתכם במאמר הזה. בחלק הראשון נציג כמה טכניקות אופטימיזציה שבהן השתמשנו בפועל בפיתוח אפליקציית The Oodles Theater. בחלק השני נדבר על הניסויים שלנו בטעינה חיזויית ועל היוזמה החדשה Guess.js.
הצורך בביצועים
האינטרנט הופך כבד יותר ויותר בכל שנה. אם בודקים את מצב האינטרנט, אפשר לראות שגודל דף ממוצע בנייד הוא כ-1.5MB, ורוב הגודל הזה מורכב מ-JavaScript ומקובצי תמונות.
הגודל ההולך וגדל של האתרים, יחד עם גורמים אחרים כמו זמן האחזור ברשת, מגבלות המעבד, דפוסי חסימה של עיבוד או קוד מיותר של צד שלישי, תורמים לבעיה המורכבת של ביצועים.
רוב המשתמשים מדרגים את המהירות כגורם החשוב ביותר בהיררכיית הצרכים שלהם בחוויית המשתמש. זה לא מפתיע מדי, כי אי אפשר לעשות הרבה עד שהדף נטען. אי אפשר להפיק ערך מהדף, אי אפשר להתפעל מהאסתטיקה שלו.
אנחנו יודעים שהביצועים חשובים למשתמשים, אבל יכול להיות שקשה להבין מאיפה להתחיל באופטימיזציה. למזלכם, יש כלים שיכולים לעזור לכם בדרך.
Lighthouse – בסיס לתהליך עבודה לשיפור הביצועים
Lighthouse הוא חלק מכלי הפיתוח ל-Chrome שמאפשר לכם לבצע ביקורת באתר ולקבל רמזים לשיפורים.
לאחרונה השקנו כמה ביקורות חדשות על הביצועים, שימושיות מאוד בתהליך העבודה היומיומי של הפיתוח.
בואו נראה איך אפשר להשתמש בהם בדוגמה מעשית: אפליקציית Oodles Theater. זוהי אפליקציית אינטרנט קטנה להדגמה, שבה אפשר לנסות כמה מסמלי ה-Doodle האינטראקטיביים האהובים שלנו ואפילו לשחק במשחק או שניים.
במהלך פיתוח האפליקציה, רצינו לוודא שהיא תפעל בצורה הכי יעילה שאפשר. נקודת ההתחלה לאופטימיזציה הייתה דוח Lighthouse.
הביצועים הראשוניים של האפליקציה שלנו, כפי שמוצגים בדוח Lighthouse, היו גרועים למדי. ברשת 3G, המשתמש צריך לחכות 15 שניות עד לציור המשמעותי הראשון, או עד שהאפליקציה הופכת לאינטראקטיבית. Lighthouse הדגיש הרבה בעיות באתר שלנו, וציון הביצועים הכולל של 23 שיקף בדיוק את זה.
המשקל של הדף היה בערך 3.4MB – היינו חייבים לצמצם את הגודל שלו.
כך התחיל האתגר הראשון שלנו בנושא ביצועים: למצוא דברים שאפשר להסיר בקלות בלי לפגוע בחוויית השימוש הכוללת.
הזדמנויות לאופטימיזציה של הביצועים
הסרת משאבים מיותרים
יש כמה דברים ברורים שאפשר להסיר בבטחה: רווחים ותגובות.
ההזדמנות הזו מודגשת ב-Lighthouse בבדיקה של CSS ו-JavaScript לא מכווצים. השתמשנו ב-webpack לתהליך ה-build, ולכן כדי לבצע מיניפיקציה פשוט השתמשנו ב-Uglify JS plugin.
הקטנת נפח היא משימה נפוצה, ולכן סביר להניח שתוכלו למצוא פתרון מוכן מראש לכל תהליך בנייה שבו אתם משתמשים.
עוד ביקורת שימושית במרחב הזה היא הפעלת דחיסת טקסט. אין סיבה לשלוח קבצים לא דחוסים, ורוב רשתות ה-CDN תומכות בכך בימינו.
השתמשנו ב-Firebase Hosting כדי לארח את הקוד שלנו, ומערכת Firebase מאפשרת gzipping כברירת מחדל, כך שפשוט קיבלנו את זה בחינם בזכות אירוח הקוד שלנו ב-CDN סביר.
gzip היא שיטה פופולרית מאוד לדחיסה, אבל גם מנגנונים אחרים כמו Zopfli ו-Brotli צוברים פופולריות. רוב הדפדפנים תומכים ב-Brotli, ואפשר להשתמש בקובץ בינארי כדי לבצע דחיסה מראש של הנכסים לפני ששולחים אותם לשרת.
שימוש במדיניות מטמון יעילה
השלב הבא היה לוודא שלא נשלח משאבים פעמיים אם אין בכך צורך.
הביקורת Inefficient cache policy ב-Lighthouse עזרה לנו להבין שאפשר לבצע אופטימיזציה של אסטרטגיות ה-caching כדי להשיג בדיוק את זה. הגדרנו כותרת תפוגה מסוג max-age בשרת שלנו, כדי לוודא שבביקור חוזר המשתמש יוכל לעשות שימוש חוזר במשאבים שהוא הוריד בעבר.
מומלץ לשמור במטמון כמה שיותר משאבים בצורה מאובטחת למשך הזמן הארוך ביותר האפשרי, ולספק אסימוני אימות כדי לאמת מחדש ביעילות את המשאבים שעודכנו.
הסרת קוד שלא נמצא בשימוש
עד עכשיו הסרנו את החלקים המיותרים והברורים של ההורדה, אבל מה לגבי החלקים הפחות ברורים? לדוגמה, קוד שלא נעשה בו שימוש.
לפעמים אנחנו כוללים באפליקציות שלנו קוד שלא באמת נחוץ. זה קורה במיוחד אם עובדים על האפליקציה במשך תקופה ארוכה, אם יש שינויים בצוות או בתלות, ולפעמים נשארת מאחור ספרייה יתומה. זה בדיוק מה שקרה לנו.
בהתחלה השתמשנו בספריית רכיבי Material כדי ליצור אב טיפוס של האפליקציה שלנו במהירות. עם הזמן עברנו למראה ולתחושה מותאמים אישית יותר, ושכחנו לגמרי מהספרייה הזו. למזלנו, הבדיקה של כיסוי הקוד עזרה לנו לגלות אותו מחדש בחבילה שלנו.
אפשר לבדוק את נתוני כיסוי הקוד ב-DevTools, גם בזמן הריצה וגם בזמן הטעינה של האפליקציה. אפשר לראות את שני הפסים האדומים הגדולים בצילום המסך התחתון – יותר מ-95% מה-CSS שלנו לא היו בשימוש, וגם הרבה JavaScript.
Lighthouse זיהה את הבעיה הזו גם בביקורת של כללי CSS שלא נמצאים בשימוש. הוא הראה חיסכון פוטנציאלי של יותר מ-400kb. אז חזרנו לקוד והסרנו את החלקים של JavaScript ו-CSS מהספרייה הזו.
השינוי הזה הקטין את חבילת ה-CSS פי 20, וזה די טוב בשביל קומיט קטן באורך שתי שורות.
כמובן, ציון הביצועים שלנו עלה, וגם הזמן עד שהאתר הופך לאינטראקטיבי השתפר מאוד.
עם זאת, כשמבצעים שינויים כאלה, לא מספיק לבדוק רק את המדדים והציונים. הסרה של קוד בפועל אף פעם לא חפה מסיכונים, ולכן תמיד צריך לחפש רגרסיות פוטנציאליות.
הקוד שלנו לא היה בשימוש ב-95% מהמקרים – עדיין יש 5% איפשהו. נראה שאחד מהרכיבים שלנו עדיין השתמש בסגנונות מהספרייה הזו – החצים הקטנים במחוון של השרבוט. אבל מכיוון שהשינוי היה קטן, יכולנו פשוט להוסיף את הסגנונות האלה בחזרה ללחצנים באופן ידני.
לכן, אם מסירים קוד, חשוב לוודא שיש לכם תהליך עבודה מתאים לבדיקה שיעזור לכם להגן על עצמכם מפני רגרסיות ויזואליות פוטנציאליות.
מומלץ להימנע ממטען ייעודי (payload) גדול מדי ברשת
אנחנו יודעים שמשאבים גדולים יכולים להאט את טעינת דפי האינטרנט. הם עלולים לעלות למשתמשים שלנו כסף ולהשפיע מאוד על חבילות הגלישה שלהם, ולכן חשוב מאוד להיות מודעים לכך.
Lighthouse הצליח לזהות בעיה בחלק ממטעני הנתונים ברשת באמצעות הביקורת Enormous network payload.
כאן ראינו שיש לנו יותר מ-3MB של קוד שמועבר – שזה די הרבה, במיוחד בנייד.
בראש הרשימה הזו, Lighthouse הדגיש שיש לנו חבילת ספקים של JavaScript בגודל 2MB של קוד לא דחוס. זו גם בעיה ש-webpack מדגיש.
כמו שאומרים: הבקשה הכי מהירה היא הבקשה שלא נשלחה.
מומלץ למדוד את הערך של כל נכס שמוצג למשתמשים, למדוד את הביצועים של הנכסים האלה ולהחליט אם כדאי להציג אותם בחוויית המשתמש הראשונית. הסיבה לכך היא שלפעמים אפשר לדחות את הטעינה של הנכסים האלה, או לטעון אותם באופן עצלני, או לעבד אותם בזמן שהמערכת לא פעילה.
במקרה שלנו, מכיוון שאנחנו עובדים עם הרבה חבילות JavaScript, היה לנו מזל כי לקהילת JavaScript יש מגוון רחב של כלים לביקורת חבילות JavaScript.
התחלנו עם webpack bundle analyzer, שדיווח לנו שכללנו תלות בשם unicode שהייתה 1.6MB של JavaScript מנותח, כלומר די הרבה.
לאחר מכן עברנו לעורך שלנו, ובעזרת התוסף Import Cost ל-Visual code הצלחנו לראות את העלות של כל מודול שייבאנו. כך יכולנו לגלות איזה רכיב כלל קוד שהפנה למודול הזה.
אחר כך עברנו לכלי אחר, BundlePhobia. זהו כלי שמאפשר להזין את השם של כל חבילת NPM ולראות מה הגודל המשוער שלה אחרי מזעור ודחיסה ב-gzip. מצאנו חלופה טובה למודול ה-slug שבו השתמשנו, שהמשקל שלה היה רק 2.2kb, אז החלפנו אותו.
השינוי הזה השפיע מאוד על הביצועים שלנו. בעקבות השינוי הזה וגילוי הזדמנויות נוספות לצמצום הגודל של חבילת ה-JavaScript, חסכנו 2.1MB של קוד.
ראינו שיפור של 65% באופן כללי, אחרי שכללנו את הגודל של החבילות האלה אחרי דחיסה ב-gzip ומיניפיקציה. גילינו שזה היה שווה את המאמץ.
לכן, באופן כללי, כדאי לנסות לצמצם את ההורדות המיותרות באתרים ובאפליקציות. כדי להבין את ההשפעה של הנכסים על הביצועים, כדאי לערוך רשימה של הנכסים ולמדוד את ההשפעה שלהם על הביצועים. לכן חשוב לבדוק את הנכסים באופן קבוע.
קיצור זמן האתחול של JavaScript באמצעות פיצול קוד
למרות שמטענים גדולים ברשת יכולים להשפיע מאוד על האפליקציה שלנו, יש עוד דבר שיכול להשפיע מאוד, וזה JavaScript.
JavaScript הוא הנכס הכי יקר שלכם. בנייד, אם אתם שולחים חבילות גדולות של JavaScript, יכול להיות שיהיה עיכוב בזמן שבו המשתמשים יוכלו לקיים אינטראקציה עם רכיבי ממשק המשתמש. כלומר, יכול להיות שהם יקישו על ממשק המשתמש בלי שמשהו משמעותי יקרה בפועל. לכן חשוב לנו להבין למה קוד JavaScript עולה כל כך הרבה.
כך דפדפן מעבד JavaScript.
קודם כל צריך להוריד את הסקריפט הזה. יש מנוע JavaScript שצריך לנתח את הקוד, לקמפל אותו ולהריץ אותו.
השלבים האלה לא לוקחים הרבה זמן במכשיר מתקדם כמו מחשב שולחני או מחשב נייד, ואולי אפילו בטלפון מתקדם. אבל בטלפון נייד ממוצע, התהליך הזה יכול להימשך פי חמישה עד פי עשרה יותר זמן. הפעולה הזו גורמת לעיכובים באינטראקטיביות, ולכן חשוב לנו לנסות לצמצם אותה.
כדי לעזור לכם לגלות את הבעיות האלה באפליקציה, הוספנו ל-Lighthouse ביקורת חדשה על זמן האתחול של JavaScript.
במקרה של אפליקציית Oodle, המערכת דיווחה לנו שמשך הזמן שחלף עד שהאפליקציה הופעלה ב-JavaScript היה 1.8 שניות. מה שקרה הוא שייבאנו באופן סטטי את כל המסלולים והרכיבים שלנו לחבילת JavaScript מונוליטית אחת.
אחת הטכניקות לעקיפת הבעיה היא שימוש בפיצול קוד.
הרעיון של פיצול קוד הוא שבמקום לתת למשתמשים פיצה שלמה של JavaScript, מה אם הייתם נותנים להם רק פרוסה אחת בכל פעם לפי הצורך?
אפשר להחיל פיצול קוד ברמת המסלול או ברמת הרכיב. היא פועלת מצוין עם React ו-React Loadable, Vue.js, Angular, Polymer, Preact ועוד הרבה ספריות אחרות.
שילבנו באפליקציה שלנו פיצול קוד, ועברנו מייבוא סטטי לייבוא דינמי, מה שמאפשר לנו לטעון קוד באופן אסינכרוני לפי הצורך.
ההשפעה הייתה כפולה: צמצום הגודל של החבילות וקיצור זמן האתחול של JavaScript. הזמן ירד ל-0.78 שניות, והאפליקציה הפכה למהירה יותר ב-56%.
באופן כללי, אם אתם יוצרים חוויה שמתבססת על JavaScript, הקפידו לשלוח למשתמש רק את הקוד שהוא צריך.
כדאי להשתמש במושגים כמו פיצול קוד, לבדוק רעיונות כמו tree shaking ולעיין במאגר webpack-libs-optimizations כדי לקבל רעיונות לצמצום הגודל של הספרייה אם אתם משתמשים ב-webpack.
בצע אופטימיזציה לתמונות
באפליקציית Oodle אנחנו משתמשים בהרבה תמונות. לצערנו, התוצאות של Lighthouse היו הרבה פחות טובות. למעשה, נכשלנו בכל שלושת הביקורות שקשורות לתמונות.
שכחנו לבצע אופטימיזציה של התמונות, לא התאמנו את הגודל שלהן בצורה נכונה, ויכולנו להרוויח משימוש בפורמטים אחרים של תמונות.
התחלנו באופטימיזציה של התמונות שלנו.
כדי לבצע סבב אופטימיזציה חד-פעמי, אפשר להשתמש בכלים ויזואליים כמו ImageOptim או XNConvert.
דרך אוטומטית יותר היא להוסיף שלב של אופטימיזציה של תמונות לתהליך הבנייה, באמצעות ספריות כמו imagemin.
כך תוכלו לוודא שהתמונות שיתווספו בעתיד יעברו אופטימיזציה באופן אוטומטי. חלק מהרשתות להעברת תוכן (CDN), למשל Akamai, או פתרונות של צד שלישי כמו Cloudinary, Fastly או Uploadcare, מציעים פתרונות מקיפים לאופטימיזציה של תמונות, כך שאתם יכולים גם לארח את התמונות בשירותים האלה.
אם אתם לא רוצים לעשות את זה בגלל העלות או בעיות של זמן אחזור, פרויקטים כמו Thumbor או Imageflow מציעים חלופות באירוח עצמי.
קובץ ה-PNG של הרקע סומן ב-webpack כגדול, ובצדק. אחרי ששינינו את הגודל שלו כך שיתאים לאזור התצוגה והרצנו אותו דרך ImageOptim, הגודל שלו ירד ל-100kb, שזה גודל סביר.
חזרנו על הפעולה הזו לגבי כמה תמונות באתר שלנו, וכך הצלחנו להקטין באופן משמעותי את המשקל הכולל של הדף.
שימוש בפורמט הנכון לתוכן מונפש
קובצי GIF יכולים להיות יקרים מאוד. באופן מפתיע, פורמט ה-GIF לא נועד מלכתחילה כפלטפורמה לאנימציה. לכן, מעבר לפורמט וידאו מתאים יותר יכול לחסוך לכם הרבה מקום בגודל הקובץ.
באפליקציית Oodle, השתמשנו ב-GIF כרצף פתיחה בדף הבית. לפי Lighthouse, אפשר לחסוך יותר מ-7MB אם נעבור לפורמט וידאו יעיל יותר. הקליפ שלנו שקל כ-7.3MB, הרבה יותר מדי בשביל אתר סביר, אז במקום זאת הפכנו אותו לרכיב וידאו עם שני קובצי מקור – mp4 ו-WebM לתמיכה רחבה יותר בדפדפנים.
השתמשנו בכלי FFmpeg כדי להמיר את קובץ ה-GIF של האנימציה לקובץ MP4. פורמט WebM מאפשר לכם לחסוך עוד יותר – ImageOptim API יכול לבצע את ההמרה הזו בשבילכם.
ffmpeg -i animation.gif -b:v 0 -crf 40 -vf scale=600:-1 video.mp4
הצלחנו לחסוך יותר מ-80% מהמשקל הכולל שלנו בזכות ההמרה הזו. כך הגענו לגודל של כ-1MB.
עם זאת, 1MB הוא משאב גדול מדי להעברה דרך הרשת, במיוחד למשתמשים עם רוחב פס מוגבל. למזלנו, יכולנו להשתמש ב-Effective Type API כדי להבין שהם משתמשים ברוחב פס איטי, ולתת להם במקום זאת קובץ JPEG קטן בהרבה.
בממשק הזה נעשה שימוש בערכים של זמן הלוך ושוב בפועל ושל זמן השבתה כדי לאמוד את סוג הרשת שבה המשתמש משתמש. היא פשוט מחזירה מחרוזת, slow 2G, 2G, 3G או 4G. לכן, בהתאם לערך הזה, אם המשתמש נמצא ברשת שהיא מתחת ל-4G, אפשר להחליף את רכיב הווידאו בתמונה.
if (navigator.connection.effectiveType) { ... }
היא אמנם פוגעת קצת בחוויית השימוש, אבל לפחות אפשר להשתמש באתר גם בחיבור איטי.
טעינה מדורגת של תמונות שלא מוצגות במסך
בדרך כלל, קרוסלות, סליידרים או דפים ארוכים מאוד טוענים תמונות, גם אם המשתמש לא יכול לראות אותן מיד בדף.
התנהגות כזו תסומן ב-Lighthouse בביקורת על תמונות שלא מוצגות במסך, ואפשר לראות אותה גם בחלונית הרשת בכלי הפיתוח. אם אתם רואים הרבה תמונות נכנסות אבל רק חלק קטן מהן מוצג בדף, כדאי לשקול להשתמש בטעינה עצלה במקום זאת.
טעינה עצלה עדיין לא נתמכת באופן מובנה בדפדפן, ולכן אנחנו צריכים להשתמש ב-JavaScript כדי להוסיף את היכולת הזו. השתמשנו בספריית Lazysizes כדי להוסיף התנהגות של טעינה עצלה ל-Oodle covers שלנו.
<!-- 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 חכמה כי היא לא רק עוקבת אחרי שינויים במידת החשיפה של האלמנט, אלא גם שולפת מראש באופן יזום אלמנטים שקרובים לאזור התצוגה כדי ליצור חוויית משתמש אופטימלית.
הוא מציע גם שילוב אופציונלי של IntersectionObserver, שמאפשר לכם לבצע בדיקות יעילות מאוד של נראות.
אחרי השינוי הזה, התמונות שלנו מאוחזרות לפי דרישה. אם אתם רוצים להעמיק בנושא, כדאי לעיין במקור המידע המקיף והשימושי images.guide.
איך עוזרים לדפדפן לספק משאבים קריטיים מוקדם
לא לכל בייט שמועבר דרך החוט לדפדפן יש אותה רמת חשיבות, והדפדפן יודע את זה. בדפדפנים רבים יש היוריסטיקה שקובעת מה צריך לאחזר קודם. לכן, לפעמים הם יאחזרו CSS לפני תמונות או סקריפטים.
אפשרות שימושית היא שאנחנו, כיוצרי הדף, נודיע לדפדפן מה באמת חשוב לנו. למזלנו, בשנים האחרונות ספקי דפדפנים הוסיפו מספר תכונות שיעזרו לנו בכך, למשל רמזים למשאבים כמו link rel=preconnect, preload או prefetch.
היכולות האלה, שהוספנו לפלטפורמת האינטרנט, עוזרות לדפדפן לאחזר את הפריט הנכון בזמן הנכון. הן יכולות להיות יעילות יותר מגישות מסוימות של טעינה מותאמת אישית שמבוססות על לוגיקה, שמתבצעות באמצעות סקריפט.
בואו נראה איך Lighthouse עוזר לנו להשתמש ביעילות בחלק מהתכונות האלה.
הדבר הראשון ש-Lighthouse מציע לנו לעשות הוא להימנע מביצוע כמה נסיעות הלוך ושוב יקרות לכל מקור.
במקרה של אפליקציית Oodle, אנחנו משתמשים הרבה ב-Google Fonts. בכל פעם שמוסיפים גיליון סגנונות של Google Fonts לדף, הוא מתחבר לעד שני תת-דומיינים. וב-Lighthouse כתוב שאם היינו מצליחים לחמם את החיבור הזה, היינו יכולים לחסוך עד 300 מילישניות מזמן החיבור הראשוני.
אם נשתמש בקישור מקדים מסוג rel, נוכל להסתיר את זמן האחזור של החיבור.
במיוחד כשמדובר ב-Google Fonts, שבו ה-CSS של משפחת הגופנים מתארח ב-googleapis.com, ומשאבי הגופנים מתארחים ב-Gstatic, יכולה להיות לכך השפעה גדולה מאוד. לכן ביצענו את האופטימיזציה הזו וקיצרנו את זמן הטעינה בכמה מאות אלפיות השנייה.
ההצעה הבאה של Lighthouse היא לטעון מראש בקשות מפתח.
<link rel=preload> הוא חזק מאוד, הוא מודיע לדפדפן שנדרש משאב כחלק מהניווט הנוכחי, והוא מנסה לגרום לדפדפן לאחזר אותו בהקדם האפשרי.
עכשיו Lighthouse אומר לנו שכדאי לטעון מראש את משאבי הגופן העיקריים באינטרנט, כי אנחנו טוענים שני גופנים באינטרנט.
טעינה מראש של גופן אינטרנט נראית כך – מציינים rel=preload, מעבירים את as עם סוג הגופן, ואז מציינים את סוג הגופן שמנסים לטעון, כמו woff2.
ההשפעה של התוכן על הדף יכולה להיות משמעותית.
בדרך כלל, בלי להשתמש בטעינה מראש של תגי rel לקישורים, אם גופני האינטרנט קריטיים לדף, הדפדפן צריך קודם לאחזר את ה-HTML, אחר כך לנתח את ה-CSS, ורק בשלב מאוחר יותר הוא יאחזר את גופני האינטרנט.
אם משתמשים ב-link rel preload, ברגע שהדפדפן מנתח את ה-HTML, הוא יכול להתחיל לאחזר את גופני האינטרנט האלה הרבה יותר מוקדם. במקרה של האפליקציה שלנו, הצלחנו לקצר בשנייה את הזמן שלקח לנו לעבד טקסט באמצעות הגופנים האינטרנטיים שלנו.
אם אתם מנסים לטעון מראש גופנים באמצעות גופנים של Google, יש נקודה אחת שצריך לשים לב אליה.
כתובות ה-URL של הגופנים של Google שאנחנו מציינים ב-font faces בגיליונות הסגנונות שלנו מתעדכנות באופן די קבוע על ידי צוות הגופנים. תוקף כתובות ה-URL האלה יכול לפוג, או שהן מתעדכנות בתדירות קבועה. לכן, אם אתם רוצים שליטה מלאה בחוויית טעינת הגופנים, אנחנו ממליצים לארח את גופני האינטרנט שלכם בעצמכם. זה יכול להיות מצוין כי זה מאפשר לכם גישה לתכונות כמו link rel preload.
במקרה שלנו, הכלי Google Web Fonts Helper היה מאוד שימושי ועזר לנו להוריד חלק מהגופנים האלה ולהגדיר אותם באופן מקומי. כדאי לנסות את הכלי הזה.
לא משנה אם אתם משתמשים בגופני אינטרנט כחלק מהמשאבים הקריטיים שלכם, או שזה קורה ב-JavaScript, נסו לעזור לדפדפן לספק את המשאבים הקריטיים שלכם בהקדם האפשרי.
תכונה ניסיונית: רמזים לגבי עדיפות
יש לנו משהו מיוחד לשתף איתך היום. בנוסף לתכונות כמו רמזים למשאבים וטעינה מראש, אנחנו עובדים על תכונה ניסיונית חדשה לגמרי בדפדפן שנקראת רמזים לגבי עדיפות.
זו תכונה חדשה שמאפשרת להעביר לדפדפן רמזים לגבי החשיבות של משאב מסוים. התכונה חושפת מאפיין חדש – importance – עם הערכים low, high או auto.
כך אנחנו יכולים להעביר את המסר על הורדת העדיפות של משאבים פחות חשובים, כמו סגנונות לא קריטיים, תמונות או קריאות ל-Fetch API, כדי להפחית את העומס. אנחנו יכולים גם להגדיל את העדיפות של דברים חשובים יותר, כמו תמונות הגיבורים שלנו.
במקרה של אפליקציית Oodle שלנו, זה הוביל למקום פרקטי אחד שבו יכולנו לבצע אופטימיזציה.
לפני שהוספנו טעינה עצלה לתמונות שלנו, הדפדפן היה מביא את כל התמונות בתחילת הקרוסלה עם עדיפות גבוהה בשלב מוקדם. לצערנו, התמונות שהיו הכי חשובות למשתמש הופיעו באמצע הקרוסלה. לכן, הגדרנו את רמת החשיבות של תמונות הרקע כנמוכה מאוד, את רמת החשיבות של התמונות בחזית כגבוהה מאוד, והתוצאה הייתה שיפור של שתי שניות במהירות שבה הצלחנו לאחזר ולהציג את התמונות האלה ברשת 3G איטית. אז זו חוויה חיובית ונעימה.
אנחנו מקווים להוסיף את התכונה הזו ל-Canary בעוד כמה שבועות, אז כדאי לעקוב.
הגדרת אסטרטגיה לטעינת גופני אינטרנט
טיפוגרפיה היא מרכיב בסיסי בעיצוב טוב, ואם אתם משתמשים בגופנים לאינטרנט, אתם לא רוצים לחסום את העיבוד של הטקסט, ובטח לא רוצים להציג טקסט בלתי נראה.
הדגשנו את זה ב-Lighthouse באמצעות הביקורת avoid invisible text while web fonts are loading (הימנעות מטקסט בלתי נראה בזמן שטוענים גופני אינטרנט).
אם אתם טוענים את גופני האינטרנט באמצעות בלוק של font face, אתם מאפשרים לדפדפן להחליט מה לעשות אם חולף זמן רב עד שגופן האינטרנט הזה נטען. חלק מהדפדפנים יחכו עד שלוש שניות לפני שיחזרו לגופן מערכת, ובסופו של דבר יחליפו אותו בגופן אחרי שהוא יורד.
אנחנו מנסים להימנע מהטקסט הבלתי נראה הזה, ולכן במקרה הזה לא היינו יכולים לראות את דפי ה-Doodle הקלאסיים של השבוע אם הגופן האינטרנטי היה נטען לאט מדי. למזלכם, עם תכונה חדשה שנקראת 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');
}
הצגת הגופן עוזרת לכם להחליט איך גופני אינטרנט יוצגו או יוחלפו בהתאם לזמן שנדרש להחלפה.
במקרה הזה אנחנו משתמשים בהחלפת תצוגה של גופן. ההגדרה swap מעניקה לגופן תקופת חסימה של אפס שניות, ותקופת החלפה אינסופית. המשמעות היא שהדפדפן יצייר את הטקסט שלכם כמעט מיד, עם גופן חלופי אם ייקח לגופן זמן להיטען. הוא יחליף את הגופן ברגע שהוא יהיה זמין.
במקרה של האפליקציה שלנו, היתרון הגדול היה שאפשר היה להציג טקסט משמעותי בשלב מוקדם מאוד, ואז לעבור לגופן האינטרנט כשהוא היה מוכן.
באופן כללי, אם אתם משתמשים בגופנים לאינטרנט, כמו אחוז גדול מהאתרים, כדאי להשתמש בשיטה טובה לטעינת גופנים לאינטרנט.
יש הרבה תכונות של פלטפורמת האינטרנט שבהן אפשר להשתמש כדי לשפר את חוויית הטעינה של הגופנים, אבל כדאי גם לעיין במאגר המתכונים של גופני אינטרנט של זאק ליתרמן, כי הוא מצוין.
הפחתת סקריפטים שחוסמים את העיבוד
יש חלקים אחרים באפליקציה שאפשר להקדים את ההורדה שלהם כדי לספק חוויית משתמש בסיסית מוקדם יותר.
בציר הזמן של Lighthouse אפשר לראות שבמהלך השניות הראשונות האלה, כשכל המשאבים נטענים, המשתמש לא יכול לראות תוכן.
ההורדה והעיבוד של גיליונות סגנונות חיצוניים חוסמים את תהליך הרינדור שלנו, ולא מאפשרים לו להתקדם.
אנחנו יכולים לנסות לבצע אופטימיזציה של נתיב העיבוד הקריטי על ידי הצגת חלק מהסגנונות קצת יותר מוקדם.
אם נחלץ את הסגנונות שאחראים לעיבוד הראשוני הזה ונציב אותם בשורה בקוד ה-HTML, הדפדפן יוכל לעבד אותם מיד בלי לחכות לגיליונות הסגנונות החיצוניים.
במקרה שלנו, השתמשנו במודול NPM שנקרא Critical כדי להטביע את התוכן הקריטי שלנו בקובץ index.html במהלך שלב בנייה.
המודול הזה עשה בשבילנו את רוב העבודה הקשה, אבל עדיין היה קצת מסובך לגרום לו לפעול בצורה חלקה במסלולים שונים.
אם לא תהיו זהירים או שמבנה האתר שלכם מורכב מאוד, יכול להיות שיהיה לכם קשה מאוד להטמיע את סוג התבנית הזה אם לא תכננתם ארכיטקטורת מעטפת אפליקציה מההתחלה.
לכן חשוב מאוד להביא בחשבון את הביצועים כבר בשלב מוקדם. אם לא תתכננו את האתר שלכם כך שיניב ביצועים טובים מההתחלה, יש סיכוי גבוה שתיתקלו בבעיות בהמשך.
בסופו של דבר, הסיכון השתלם. הצלחנו לגרום לזה לעבוד והאפליקציה התחילה להציג תוכן הרבה יותר מוקדם, וכך שיפרנו באופן משמעותי את הזמן להצגת התוכן העיקרי (FMP).
התוצאה
זו הייתה רשימה ארוכה של אופטימיזציות לשיפור הביצועים שיישמנו באתר שלנו. בואו נראה את התוצאה. כך האפליקציה שלנו נטענה במכשיר נייד בינוני ברשת 3G, לפני ואחרי האופטימיזציה.
ציון הביצועים ב-Lighthouse עלה מ-23 ל-91. ההתקדמות שלך מבחינת מהירות היא די טובה. כל השינויים האלה התבססו על בדיקות שערכנו באופן שוטף ועל המידע שמופיע בדוח Lighthouse. אם אתם רוצים לראות איך יישמנו את כל השיפורים מבחינה טכנית, אתם מוזמנים לעיין במאגר שלנו, במיוחד בבקשות למשיכת קוד (PR) שנוספו לשם.
ביצועים מבוססי-תחזיות – חוויות משתמש שמבוססות על נתונים
אנחנו מאמינים שלמידת מכונה מייצגת הזדמנות מרתקת לעתיד בתחומים רבים. רעיון אחד שאנחנו מקווים שיעודד ניסויים נוספים בעתיד הוא שנתונים אמיתיים יכולים לעזור לנו ליצור חוויות משתמש טובות יותר.
כיום, אנחנו מקבלים הרבה החלטות שרירותיות לגבי מה שהמשתמש עשוי לרצות או להצטרך לו, ולכן מה שכדאי לאחזר מראש, לטעון מראש או לשמור במטמון מראש. אם הניחוש שלנו נכון, אנחנו יכולים לתת עדיפות לכמות קטנה של משאבים, אבל קשה מאוד להרחיב את זה לכל האתר.
יש לנו נתונים זמינים שיכולים לעזור לנו לשפר את האופטימיזציות שלנו כבר היום. באמצעות Google Analytics Reporting API אנחנו יכולים לבדוק את הדף הבא הכי פופולרי ואת אחוז היציאה לכל כתובת URL באתר שלנו, וכך להסיק מסקנות לגבי המשאבים שצריך לתת להם עדיפות.
אם נשלב את זה עם מודל הסתברות טוב, נוכל להימנע מבזבוז נתוני המשתמשים על ידי טעינה מראש של תוכן בצורה אגרסיבית מדי. אנחנו יכולים להשתמש בנתונים האלה מ-Google Analytics, ולהטמיע מודלים כאלה באמצעות למידת מכונה ומודלים כמו שרשראות מרקוב או רשתות עצביות.
כדי להקל על הניסויים האלה, אנחנו שמחים להכריז על יוזמה חדשה שנקראת 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 Doodles.