Profiling با React DevTools

در طول این فصل، چند بار روی این نکته تأکید کردیم که پیش از هر بهینه‌سازی باید ابتدا اندازه‌گیری کرد، نه حدس زد. در این درس آخر فصل، با ابزاری که دقیقاً برای همین اندازه‌گیری ساخته شده آشنا می‌شویم: تب Profiler در افزونه React Developer Tools.

React DevTools چیست

React Developer Tools یک افزونه رسمی برای مرورگرهایی مانند Chrome و Firefox است که به شما اجازه می‌دهد Component Tree برنامه، Props و State هر کامپوننت، و رفتار Render آن‌ها را مستقیماً در ابزار توسعه‌دهنده مرورگر ببینید. این افزونه دو تب اصلی دارد: Components، برای مرور ساختار درخت و بازرسی State/Props؛ و Profiler، که موضوع این درس است.

ضبط یک Session با Profiler

کار با Profiler به این شکل است: روی دکمه ضبط کلیک می‌کنید، سپس در برنامه تعاملی انجام می‌دهید که می‌خواهید بررسی کنید (مثلاً تایپ در یک فیلد جست‌وجو یا کلیک روی یک دکمه)، و در پایان ضبط را متوقف می‌کنید. Profiler حالا یک گزارش کامل از تمام Renderهایی که در این بازه رخ داده، در اختیارتان می‌گذارد.

خواندن نمودار Flame

خروجی اصلی Profiler، نموداری موسوم به Flame Chart است. هر Render، به‌صورت یک نوار افقی نمایش داده می‌شود؛ عرض هر نوار تقریباً متناسب با زمانی است که آن کامپوننت و فرزندانش صرف Render شدن کرده‌اند. کامپوننت‌هایی که اصلاً در آن Commit دوباره Render نشده‌اند (مثلاً به‌خاطر React.memo)، اصلاً در آن نوار خاص ظاهر نمی‌شوند یا با رنگ خاکستری مشخص می‌شوند.

با کلیک روی هر کامپوننت در این نمودار، جزئیاتی مثل مدت زمان دقیق Render آن و اینکه چند بار در کل Session ضبط‌شده دوباره Render شده، نمایش داده می‌شود.

«چرا این کامپوننت دوباره Render شد؟»

یکی از مفیدترین قابلیت‌های Profiler، نمایش دلیل هر Render است. با فعال کردن گزینه مربوطه در تنظیمات افزونه، برای هر کامپوننت در نمودار، می‌توانید ببینید آیا به‌خاطر تغییر Props، تغییر State، یا Render شدن والدش دوباره اجرا شده است؛ همان سه دلیلی که در درس ششم همین فصل بررسی کردیم.

استفاده از Profiler برای تأیید یک بهینه‌سازی

Profiler فقط برای پیدا کردن مشکل نیست؛ برای تأیید نتیجه یک تغییر هم به همان اندازه مفید است. الگوی رایج این است: یک Session قبل از اضافه کردن React.memo یا useMemo ضبط کنید، همان تغییر را اعمال کنید، دوباره همان تعامل را ضبط کنید، و دو نتیجه را مقایسه کنید. اگر تفاوت محسوسی در تعداد یا مدت Renderها دیده نشد، آن بهینه‌سازی احتمالاً ارزش پیچیدگی اضافه‌شده به کد را نداشته است؛ دقیقاً همان هزینه‌ای که در درس ششم فصل درباره Trade-off های memoization دیدیم.

یک نکته مهم: Profiling در حالت Production

نسخه توسعه (Development) React، به‌خاطر بررسی‌های اضافه (مثل همان اجرای دوبار Effect که در فصل ششم دیدیم)، کمی کندتر از نسخه واقعی است که کاربران نهایی استفاده می‌کنند. برای اندازه‌گیری دقیق‌تر زمان واقعی Render، بهتر است از یک Build مخصوص Profiling در حالت Production استفاده شود که مستندات رسمی React نحوه ساخت آن را توضیح می‌دهند؛ در غیر این صورت، اعداد به‌دست‌آمده در حالت توسعه، ممکن است بدتر از واقعیت به نظر برسند.

یک روش عملی برای شروع

اگر مشکوک هستید بخشی از برنامه بیش از حد Render می‌شود، یک روال ساده این است: افزونه را نصب کنید، تب Profiler را باز کنید، Session کوتاهی از همان تعامل مشکوک ضبط کنید، و به نمودار Flame نگاه کنید تا ببینید کدام کامپوننت‌ها، چند بار و با چه دلیلی ظاهر شده‌اند. این اطلاعات دقیقاً همان چیزی است که تصمیم‌گیری بین راه‌حل‌های این فصل (جداسازی ساختار، React.memo، useMemo یا useCallback) را روی داده واقعی بنا می‌کند، نه حدس.

جمع‌بندی

تب Profiler در React Developer Tools، با ضبط یک بازه از تعامل کاربر، نموداری از تمام Renderهای رخ‌داده، مدت زمان هرکدام و دلیل وقوع آن‌ها نشان می‌دهد. این ابزار هم برای پیدا کردن محل واقعی یک مشکل عملکردی، و هم برای تأیید اینکه یک بهینه‌سازی واقعاً اثر داشته، استفاده می‌شود. با این درس، فصل سیزدهم به پایان می‌رسد و در ادامه به آزمون فصل ۱۳ می‌رویم.