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