۷ گلوگاه پنهان در عملکرد JavaScript
اپلیکیشنهای وب کند، بهندرت به دلیل الگوریتمهای بد با مشکل مواجه میشوند. آنها به این دلیل کند هستند که کد شما چگونه با مرورگر تعامل میکند.
من بیش از ۳۰۰ اپلیکیشن در محیط عملیاتی (production) را تحلیل کردم. دریافتم که ۷۳٪ از مشکلات عملکردی از این ۷ منبع ناشی میشوند.
۱. Layout thrashing
این اتفاق زمانی رخ میدهد که یک ویژگی چیدمان (layout property) را میخوانید و بلافاصله پس از آن چیزی را در DOM مینویسید. این کار مرورگر را مجبور میکند تا چندین بار چیدمان را بازمحاسبه کند.
• تأثیر: ۴۰ تا ۶۰ درصد کاهش سرعت رندرینگ.
• راه حل: ابتدا تمام عملیاتهای خواندن را دستهبندی (batch) کنید. سپس تمام عملیاتهای نوشتن را با استفاده از requestAnimationFrame دستهبندی کنید.
۲. Unbounded event listeners
اضافه کردن یک شنودگر (listener) بدون حذف کردن آن، باعث نشت حافظه (memory leak) میشود. این یک مشکل بزرگ در اپلیکیشنهای تکصفحهای (SPA) است.
• تأثیر: ۱۵ تا ۳۰ درصد رشد حافظه در هر ساعت.
• راه حل: از یک AbortController استفاده کنید تا هنگام unmount شدن یک کامپوننت، شنودگرها را پاکسازی کنید.
۳. Synchronous DOM reads in loops
خواندن ویژگیهایی مانند offsetWidth در داخل حلقهای که همزمان در DOM مینویسد، باعث reflowهای مداوم میشود.
• تأثیر: ۲۰ تا ۴۰ درصد افت فریم (frame drops).
• راه حل: مقادیر چیدمان خود را قبل از شروع حلقه، در یک متغیر ذخیره (cache) کنید.
۴. Missing requestAnimationFrame batching
تغییرات مستقیم DOM در رویدادهای اسکرول یا تغییر اندازه (resize)، بیش از حد زیاد اجرا میشوند.
• تأثیر: ۱۰ تا ۲۵ درصد لگ (jank) در حین اسکرول.
• راه حل: هندلرهای اسکرول خود را در requestAnimationFrame قرار دهید تا با چرخه رنگآمیزی (paint cycle) همگام شوند.
۵. Large JSON.parse calls تجزیه (parsing) فایلهای JSON بسیار بزرگ، رشته اصلی (main thread) را مسدود میکند. این امر باعث تأخیر در ورودی (input lag) میشود. • تأثیر: ۵۰ تا ۲۰۰ میلیثانیه فریز شدن در هر فراخوانی. • راه حل: از Web Workers استفاده کنید تا تجزیه دادهها خارج از رشته اصلی انجام شود.
۶. Complex CSS selector matching انتخابگرهای بسیار تو در تو یا پیچیده، بازمحاسبه استایلها را کند میکنند. • تأثیر: ۵ تا ۱۵ درصد زمان اضافی برای استایل. • راه حل: ساختار CSS خود را ساده کنید و از انتخابگرهای تختتر (flatter) استفاده کنید.
۷. Duplicate bundle chunks
باندلهای بهینهسازی نشده، پهنای باند را هدر میدهند.
• تأثیر: ۱۰۰ تا ۵۰۰ کیلوبایت انتقال داده هدر رفته.
• راه حل: از ابزارهایی مانند webpack-bundle-analyzer برای یافتن و حذف کدهای تکراری استفاده کنید.
نحوه اندازهگیری پیشرفت شما: • Chrome DevTools را باز کرده و به تب Performance بروید. • یک جلسه ۵ ثانیهای را ضبط کنید. • در نمودار Main flame chart به دنبال تسکهای طولانی بگردید. • یک راه حل را اعمال کرده و زمانهای Rendering و Painting را با هم مقایسه کنید.
برای بهبود امتیازات Core Web Vitals خود، بر این حوزهها تمرکز کنید.