7 צווארי בקבוק נסתרים ב-JavaScript ואיך לתקן אותם
אפליקציות אינטרנט איטיות כמעט אף פעם לא נכשלות בגלל אלגוריתמים גרועים. הן נכשלות בגלל האופן שבו הקוד שלכם מתקשר עם הדפדפן.
ביצעתי פרופילציה (profiling) ל-300 אפליקציות בסביבת ייצור. 73% מבעיות הביצועים נובעות מ-7 המקורות הללו.
- Layout thrashing זה קורה כשקוראים מאפיין, כותבים ל-DOM, ואז קוראים שוב. זה מאלץ את הדפדפן לחשב מחדש את ה-layout שוב ושוב.
- פתרון: בצעו את כל פעולות הקריאה במקבץ (batch) אחד תחילה. לאחר מכן, בצעו את כל פעולות הכתיבה במקבץ באמצעות
requestAnimationFrame.
- Unbounded event listeners הוספת event listener מבלי להסיר אותו יוצרת דליפות זיכרון (memory leaks). זו בעיה מרכזית באפליקציות בעמוד בודד (SPA).
- פתרון: השתמשו ב-
AbortControllerכדי לנקות מאזינים כאשר רכיבים עוברים unmount.
- Synchronous DOM reads in loops
קריאה של
offsetWidthאוgetBoundingClientRectבתוך לולאה גורמת ל-reflows מתמשכים.
- פתרון: שמרו את ערכי ה-layout במשתנה (cache) לפני תחילת הלולאה.
- Missing requestAnimationFrame batching שינויי DOM ישירים באירועי scroll או resize מתבצעים בתדירות גבוהה מדי. זה גורם ל-jank.
- פתרון: השתמשו במשתנה ticking וב-
requestAnimationFrameכדי לסנכרן עדכונים עם מחזור ה-paint.
- Large JSON.parse payloads ניתוח (parsing) של קבצים גדולים חוסם את ה-main thread. זה גורם לעיכוב בקלט (input lag).
- פתרון: השתמשו ב-Web Workers כדי לבצע את ה-parsing של הנתונים מחוץ ל-main thread.
- Complex CSS selector matching סלקטורים מקוננים עמוק או מורכבים מאטים את חישוב מחדש של הסטייל.
- פתרון: השתמשו ב-Lighthouse כדי למצוא layout shifts ופשטו את הסלקטורים שלכם.
- Duplicate bundle chunks bundles גדולים ולא אופטימליים מבזבזים זמן העברה.
- פתרון: השתמשו ב-
webpack-bundle-analyzerכדי למצוא ולהסיר קוד כפול.
איך למדוד את ההתקדמות שלכם:
- פתחו את Chrome DevTools.
- עברו ללשונית Performance.
- הקליטו סשן של 5 שניות.
- חפשו משימות ארוכות מ-50ms ב-Main flame chart.
- יישמו תיקון אחד והשוו את זמני ה-Rendering וה-Painting.
תיקון תחומים אלו ישפר את ה-Core Web Vitals שלכם, ובמיוחד את ה-Largest Contentful Paint ואת ה-Interaction to Next Paint.