
Performance در React سالهاست که به مجموعهای از تصمیمهای دستی وابسته بوده ؛
تصمیمهایی مثل اینکه کجا memoization لازم است، چه زمانی باید identityها را پایدار نگه داشت و کدام render «واقعاً» هزینهبر است.
ابزارهایی مثل useMemo، useCallback و React.memo به ما کمک کردند این کنترل را تا حدی به دست بگیریم،
اما همزمان یک واقعیت را هم پررنگتر کردند:
Performance در React بیش از حد به قضاوت انسانی وابسته شد.
وابستگی به dependency arrayها، تشخیص renderهای غیرضروری و پیشبینی رفتار runtime،در پروژههای واقعی بهمرور به منبع پیچیدگی، خطای پنهان و کدهای fragile تبدیل شدند؛کدی که کار میکند، اما بهسختی قابل تحلیل و نگهداری است.React Compiler که بهصورت رسمی در React 19 معرفی شده،
تلاش میکند این مدل ذهنی را تغییر دهد ولی نه با اضافه کردن API جدید،بلکه با انتقال بخش بزرگی از تصمیمهای Performanceز runtime و دست developer به مرحلهی compile-time.
Performance یه ویژگی تصادفی نیست که موقع اجرا «ببینیم چی میشه».Performance نتیجهی تحلیل ساختاری کده.و این دقیقاً جاییه که React Compiler وارد میشه.
React Compiler (که قبلاً با اسم React Forget شناخته میشد)
یک تغییر ذهنی مهم میاره:
Performance از «الگوی کدنویسی» به «نتیجهی کامپایل» تبدیل میشه.
بهجای اینکه Developer بگه:
«اینجا memo کن»
Compiler میگه:
«من کدت رو تحلیل میکنم و خودم تصمیم میگیرم.»
در مرحلهی build:
dependencyهای واقعی رو استاتیک تحلیل میکنه
renderهای غیرضروری رو تشخیص میده
expressionها و componentها رو auto-memoize میکنه
بدون تغییر رفتار runtime اپ
بیاین مثال ببینیم :
قبل (React ≤ 18)
const handleClick = useCallback(() => { submit(formData) }, [formData])
function Form({ formData }) { const handleClick = () => { submit(formData) } }
یا این یکی :
قبل:
const filteredUsers = useMemo(() => { return users.filter(u => u.isActive) }, [users])
این کد خیلی تمیز به نظر میاد.
اما واقعیت؟
هر تغییری در reference users → recompute
dependency به data structure، نه به intent
اگر جای تولید users تغییر کنه، این memo بیارزش میشه
اینجا Performance به دانش انسانی از upstream data وابستهست.
function ActiveUsers({ users }) { const filteredUsers = users.filter(u => u.isActive) }
React Compiler:
تشخیص میده این محاسبه pureـه
فقط زمانی recompute میکنه که واقعاً لازم باشه
بدون dependency array شکننده
📌 نتیجه:
Performance بدون قفل شدن معماری به referenceها
const Header = React.memo(({ }) => { ... }) const App = () => { const = useCallback((q) => { search(q) }, []) return <Header ={} /> }
مشکل اینجا چیه؟
Parent مجبور به memo برای child شده
API کامپوننتها با Performance گره خورده
refactor ساده → احتمال break شدن memo
این یعنی:
Performance به interface کامپوننت نشت کرده
function Header({ }) { ... } function App() { const = (q) => { search(q) } return <Header ={} /> }
Compiler:
تشخیص میده onSearch stableـه
re-render غیرضروری رو حذف میکنه
بدون اینکه API کامپوننت آلوده بشه
📌 معماری تمیز میمونه، Performance هم حفظ میشه.
نه.
ولی از «default behavior» به «exception» تبدیل میشن.
مواردی که هنوز لازمن:
تعامل با libهایی که به reference حساسن
optimizationهای بسیار خاص
boundaryهای مشخص (مثلاً context providerها)
همین دیگه امیدوارم مفید باشه براتون :) اینم لینک https://react.dev/learn/react-compiler/introduction برای مطالعه بیشتر
سوالی داشتین بپرسین تو کامنت ها