React Compiler چه کاری انجام می دهد؟ – انجمن DEV

React Compiler ابزاری برای بهینه سازی برنامه های React است. کامپایلر زمانی که برنامه ساخته میشود وارد عمل میشود و کد را به گونهای تبدیل میکند که از رندرهای غیرضروری جلوگیری کند.
کامپایلر کد را تجزیه و تحلیل میکند، نمایش سادهشده آن را کامپایل میکند، مکانهایی را پیدا میکند که میتوانند بهینه شوند و کد انتخابشده را تبدیل میکنند. کامپایلر React فرض می کند که کد قوانین React را برآورده می کند – چنین کدی به دلیل بهینه سازی کامپایلر شکسته نمی شود. اگر کد مطابق با قوانین نباشد، نادیده گرفته می شود.
کامپایلر حداقل دو تبدیل را در کد اعمال می کند: نتیجه رندر و نتیجه محاسبه عبارات داخل اجزا را به حافظه می سپارد.
به خاطر سپردن نتیجه رندر
من نتیجه رندر را عبارتی که از کامپوننت برگردانده می شود می نامم: return
{items}
، در این مثال
{items}
– رندر نتیجه نتیجه رندر بستگی به props و مقادیر میانی محاسبه شده در داخل کامپوننت دارد. بیایید این مقادیر را وابستگی های بیانی بنامیم. هنگامی که نتیجه رندر تحت همان وابستگی ها ثابت می ماند، ارزیابی عبارت را می توان نادیده گرفت. برای انجام این کار، React Compiler کدی را وارد می کند که آخرین نتیجه محاسبه را به خاطر می آورد:
- اگر عبارت برای اولین بار ارزیابی شود، عبارت را ارزیابی می کند، نتیجه را در حافظه پنهان ذخیره می کند و وابستگی ها را در حافظه پنهان ذخیره می کند.
- اگر عبارت دوباره ارزیابی شود، مقادیر وابستگی جدید را با مقادیر ذخیره شده در حافظه پنهان مقایسه می کند:
- اگر مساوی باشند، از مقدار حافظه پنهان عبارت استفاده می کند.
- اگر آنها متفاوت باشند، عبارت را با وابستگی های جدید ارزیابی می کند، نتیجه محاسبه و وابستگی ها را در حافظه پنهان ذخیره می کند.
این جزء:
function Div({ item, other }) {
return <div data-x={other}>{item}div>;
}
React Compiler به صورت زیر تبدیل می شود:
import { c as _c } from "react/compiler-runtime";
function Div(t0) {
const $ = _c(3);
const { item, other } = t0;
let t1;
if ($[0] !== item || $[1] !== other) {
t1 = <div data-x={other}>{item}div>;
$[0] = item;
$[1] = other;
$[2] = t1;
} else {
t1 = $[2];
}
return t1;
}
می توانید آن را در خط حدس بزنید const $ = _c(3)
React Compiler یک کش محلی از 3 عنصر ایجاد می کند. در واقع، c
از react/compiler-runtime تماس داخلی React.useMemo.
در موردی که کامپوننت از قلاب یا زمینه استفاده می کند، کد تولید شده کمی پیچیده تر به نظر می رسد، اما ایده یکسان است: وابستگی های فعلی کامپوننت را با موارد ذخیره شده مقایسه کنید، اگر تغییر کرده اند، وابستگی های جدید را ذخیره کنید، وابستگی های جدید را محاسبه کنید. مقدار، مقدار جدید را کش کنید.
کد در مثال بالا شبیه به قرار دادن یک جزء در یادداشت است.
حفظ کردن عبارات
در مثال بالا، عبارت jsx فقط به اجزای کامپوننت بستگی داشت. اغلب، مؤلفهها مقادیر میانی را محاسبه میکنند که در عبارات jsx جایگزین میشوند. این مقادیر میانی را نیز می توان به خاطر بسپارید. برای انجام این کار، React Compiler وابستگی های عبارت را شناسایی می کند و کدی را برای ذخیره کل عبارت بر اساس آن وابستگی ها درج می کند.
بیایید به مثالی نگاه کنیم که در آن یک محاسبه در داخل یک جزء اتفاق می افتد:
export default function App(props) {
const name = props.fullname.split(' ')[0];
return <main>
{name}
main>;
}
در این مثال
یک عبارت jsx است، وابستگی آن یک متغیر است name
، که به نوبه خود با عبارت بالا محاسبه می شود props.fullname.split(' ')[0]
. بیان props.fullname.split(' ')[0]
فقط به پایه بستگی دارد fullname
.
React Compiler این کامپوننت را به صورت زیر تبدیل می کند:
import { c as _c } from "react/compiler-runtime";
export default function App(props) {
const $ = _c(4);
let t0;
if ($[0] !== props.fullname) {
t0 = props.fullname.split(" ");
$[0] = props.fullname;
$[1] = t0;
} else {
t0 = $[1];
}
const name = t0[0];
let t1;
if ($[2] !== name) {
t1 = <main>{name}main>;
$[2] = name;
$[3] = t1;
} else {
t1 = $[3];
}
return t1;
}
React Compiler کش خواهد شد props.fullname
و نتیجه محاسبه name
. اگر لوازم fullname
تغییر می کند، عبارت دوباره ارزیابی و ذخیره می شود. این کد شبیه به بسته بندی محاسبه است name
V useMemo
در جزء منبع:
import {useMemo} from 'react';
export default function App(props) {
const name = useMemo(() => props.fullname.split(' ')[0], [props.fullname]);
return <main>
{name}
main>;
}
فعال کردن React Compiler ممکن است در پروژهای که آگاهانه از useMemo و memo استفاده میکند، هیچ مزیت قابلتوجهی نداشته باشد.