React Compiler دقیقاً چی کار میکنه؟
خلاصهٔ کاملتر
نویسنده میگه برای اینکه یه چیزی رو خوب یاد بگیره، باید اونو برای بقیه توضیح بده. برای همین سراغ React Compiler (یعنی ابزاری که موقع build کد کامپوننتهای React رو خودکار بهینه میکنه) رفته و بهجای شروع از کد داخلیش، اول خروجیش رو بررسی کرده. نمودارهای مقاله نشون میدن با کامپایلر میشه React رو خیلی سریعتر کرد، ولی خودش تأکید میکنه که این سرعتها فعلاً فقط نمونهٔ اولیه هستن.
تو سادهترین مثال، یه کامپوننت Thing که یه دکمه با onClick برمیگردونه، بعد از کامپایل این شکلی میشه:
const $ = _c(1);
let t0;
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
t0 = <button onClick={_temp} />;
$[0] = t0;
} else {
t0 = $[0];
}تابع _c به کامپوننت چند تا خونهٔ کش (cache slot) میده، اینجا فقط یکی. مقدار Symbol.for("react.memo_cache_sentinel") یعنی «این خونه هنوز خالیه». اگه خالی باشه JSX ساخته و ذخیره میشه، وگرنه همون مقدار قبلی برمیگرده. هندلر inline هم به یه تابع سطح بالا به اسم _temp منتقل شده که بهش میگن outlining (برعکس inlining). نویسنده میگه این عملاً مثل اینه که دور همهچیز useMemo بذاری؛ شاید زیادهروی به نظر بیاد، ولی تو مقیاس بالا سریعتره.
نکتهٔ جالبتر جاییه که کامپایلر از محدودیتهای rules of hooks (یعنی قانونی که میگه هوکها نباید شرطی صدا زده بشن) رد میشه. اگه کامپوننت یه return زودهنگام داشته باشه، نمیتونی useMemo رو بعد از if بذاری، و اگه قبلش بذاری برای حالت return زودهنگام کار اضافه کردی. کامپایلر با همون API سطح پایین کش، فقط وقتی stuff عوض شده باشه دکمه رو از نو میسازه. به گفتهٔ نویسنده این API برای خوندن آزاردهندهست و برای همین React اونو به کاربر نمیده، ولی یه هدف کامپایل عالیه.
مثال آخر مقاله یه کامپوننت Toolbar هست که آرایهٔ actions رو از getActions(user) میگیره و اگه canEdit باشه بهش "Edit" اضافه میکنه. کامپایلر میفهمه این دو کار با هم روی یه مقدار تغییر ایجاد میکنن (mutate together)، پس ساختن و تغییر دادن actions رو تو یه بلوک کش میذاره که فقط وقتی user یا canEdit عوض بشه دوباره اجرا میشه. یعنی دیگه لازم نیست خودت حواست به وابستگیها باشه.
نکات کلیدی:
- خروجی کامپایلر از _c(n) از پکیج react/compiler-runtime برای گرفتن n خونهٔ کش استفاده میکنه
- Symbol.for("react.memo_cache_sentinel") مقدار «خالی» خونههای کشه
- هندلرهای inline به تابعهای سطح بالا مثل _temp منتقل میشن (outlining)
- کامپایلر میتونه بعد از return زودهنگام هم کش کنه، کاری که با useMemo بهخاطر rules of hooks شدنی نیست
- بهینهسازیهای پیشنهادی نویسنده فقط نمونهٔ اولیه هستن، نه پیشنهاد نهایی




