کامپایلر React

این صفحه مقدمه ای برای کامپایلر React و نحوه استفاده موفق آن به شما ارائه می دهد.
کامپایلر React کامپایلر جدیدی در مرحله بتا است که برای دریافت بازخوردهای زودهنگام از جامعه توسعه دهندگان، آن را به صورت متن باز منتشر کرده ایم. در حالی که این کامپایلر در حال حاضر برای محیط عملیاتی در Meta مورد استفاده قرار میگیرد، اما بکارگیری آن برای محیط عملیاتی خود سلامت کدبیس و اعمال بکارگیری قوانین React بر روی آن بستگی دارد. این فقط ابزاری برای زمان ساخت است که به طور خودکار برنامه React شما را بهینه میکند. با JavaScript ساده کار کرده و قوانین React را درک میکند، بنابراین نیازی به بازنویسی کد خود برای استفاده از آن ندارید.
کامپایلر همچنین شامل پلاگین ESLint برای نمایش تحلیلهای کامپایلر در ویرایشگر است. ما قویا به همه توصیه میکنیم که از لینتر استفاده کنند. لینتر نیازی به نصب کامپایلر ندارد، بنابراین حتی بدون امتحان کردن کامپایلر هم می توانید از آن استفاده کنید.
کامپایلر در حال حاضر به صورت beta
منتشر شده و برای آزمایش در برنامهها و کتابخانههای React 17+ در دسترس است. برای نصب نسخه بتا دستور زیر :
npm install -D babel-plugin-react-compiler@beta eslint-plugin-react-compiler@beta
یا اگر از Yarn استفاده میکنید دستور زیر را اجرا کنید:
yarn add -D babel-plugin-react-compiler@beta eslint-plugin-react-compiler@beta
اگر هنوز از React 19 استفاده نمیکنید، لطفاً بخش استفاده از کامپایلر React با React 17 یا 18 را برای مطالعه دستورالعملهای بیشتر مطالعه کنید.
کامپایلر چه کار می کند؟
برای بهینهسازی برنامهها، کامپایلر React به طور خودکار کد را بخاطر سپاری (memoizing) میکند. ممکن است در حال حاضر با بخاطر سپاری از طریق APIهایی مانند useMemo
، useCallback
و React.memo
آشنا باشید. با این APIها میتوانید به React بگویید که برخی بخشهای برنامه شما با وجود تغییر نکردن ورودی هایشان نیازی به محاسبه مجدد ندارند، اینکار باعث کاهش کار در بروزرسانیها میشود. هرچند این یک قابلیت قدرتمند است، اما به سادگی می توان عملکرد آن را فراموش کرد یا به اشتباه از آن استفاده کرد که ممکن است منجر به بروزرسانیهای ناکارآمد به خاطر بررسی بخش های تغییر نکرده برنامه توسط می شود.
کامپایلر از دانش خود در JavaScript و قوانین React استفاده کرده و به طور خودکار مقادیر یا گروههایی از مقادیر را درون کامپوننتها و هوکهای شما به خاطر می سپرد. اگر نقض قوانینی را تشخیص دهد، به طور خودکار از آن کامپوننتها یا هوکها گذر کرده و به صورت ایمن سایر کدها را کامپایل میکند. کامپایلر React به راحتی امکان پیدا کردن نقض قوانین و رد شدن از بهینه سازی کامپوننت ها و هوک های دارای این نقض ها را دارد. برای کامپایلر بهینه سازی 100 درصدی کد شما ضرورتی ندارد.
اگر در کدبیس شما قبلاً به خوبی از به ابزارهای بخاطر سپاری استفاده شده باشد، انتظار افزایش قابل توجه عملکرد برنامه بوسیله کامپایلر را نداشته باشید. با این حال، در عمل، به خاطر سپاری وابستگیهای درست که باعث مشکلات عملکردی میشوند، به صورت دستی کار دشواری است.
چه نوع به خاطر سپاری هایی بوسیله کامپایلر به کد اضافه می شود؟
انتشار اولیه کامپایلر React عمدتاً بر روی بهبود عملکرد بروزرسانی (بروزرسانی مجدد کامپوننتهای موجود) متمرکز است، بنابراین تمرکز بر روی این دو مورد است:
- صرف نظر کردن از بروزرسانی مجدد آبشاری کامپوننتها
- بروزرسانی مجدد
<Parent />
باعث میشود بسیاری از کامپوننتها در درخت کامپوننت آن دوباره بروزرسانی شوند، حتی اگر فقط<Parent />
تغییر کرده باشد
- بروزرسانی مجدد
- صرف نظر کردن از محاسبات سنگین خارج از React
- به عنوان مثال، فراخوانی
expensivelyProcessAReallyLargeArrayOfObjects()
درون کامپوننت یا هوکی که به آن داده نیاز دارد
- به عنوان مثال، فراخوانی
بهینهسازی بروزرسانیهای مجدد
React به شما این امکان رو میدهد تا رابط کاربری خود را به صورتی تابعی از وضعیت فعلی آن بیان کنید (به طور دقیقتر: ورودی ها، وضعیت و کانتکست آنها). در پیادهسازی کنونی، وقتی وضعیت یک کامپوننت تغییر کند، React آن کامپوننت و همه فرزندانش را دوباره بروزرسانی میکند — مگر اینکه به خاطر سپاری را به صورت دستی با یکی از این هوک ها useMemo()
، useCallback()
، یا React.memo()
برای کامپوننت اعمال کرده باشید. برای مثال، در کد زیر، <MessageButton>
هر بار که وضعیت <FriendList>
تغییر کند، دوباره بروزرسانی میشود:
function FriendList({ friends }) {
const onlineCount = useFriendOnlineCount();
if (friends.length === 0) {
return <NoFriends />;
}
return (
<div>
<span>{onlineCount} online</span>
{friends.map((friend) => (
<FriendListCard key={friend.id} friend={friend} />
))}
<MessageButton />
</div>
);
}
این مثال را در زمین بازی کامپایلر React ببینید
کامپایلر React به طور خودکار معادل به خاطر سپاری دستی را بر روی کد اعمال میکند و اطمینان میدهد که فقط بخشهای مرتبط، با تغییر وضعیت دوباره بروزرسانی شوند، که گاهی اوقات به "واکنشپذیری دقیق" تعبیر میشود. در مثال بالا، کامپایلر React تشخیص می دهد که مقدار برگشتی <FriendListCard />
حتی با تغییر friends
دوباره می تواند مورد استفاده قرار بگیرد و از دوباره سازی JSX آن و بروزرسانی مجدد <MessageButton>
در صورت تغییر تعداد آنلاین جلوگیری کند.
محاسبات سنگین نیز به خاطر سپرده میشوند
کامپایلر همچنین میتواند به طور خودکار محاسبات سنگین که در طول رندرینگ استفاده میشوند را به خاطر بسپارد
// این کد بوسیله کامپایلر تا زمانی که کامپوننت و هوک نباشد به خاطر سپرده نمی شود
function expensivelyProcessAReallyLargeArrayOfObjects() { /* ... */ }
// بوسیله کامپایلر بدلیل کامپوننت بودن به خاطر سپرده می شود
function TableContainer({ items }) {
// این فراخوانی تابع به خاطر سپرده می شود:
const data = expensivelyProcessAReallyLargeArrayOfObjects(items);
// ...
}
این مثال را در زمین بازی کامپایلر React ببینید
با این حال، اگر expensivelyProcessAReallyLargeArrayOfObjects
واقعاً یک تابع سنگین باشد، ممکن است فرآیند به خاطر سپردن را به طور مستقل در خارج از React پیادهسازی کنید، زیرا:
- کامپایلر React فقط کامپوننتها و هوکهای React را ممو میکند، نه هر تابعی را
- ممو کردن کامپایلر React در سراسر کامپوننتها یا هوکهای مختلف به اشتراک گذاشته نمیشود
بنابراین اگر expensivelyProcessAReallyLargeArrayOfObjects
در بسیاری از کامپوننتهای مختلف استفاده شده باشد، حتی اگر همان موارد دقیقاً منتقل شده باشند، آن محاسبه سنگین بارها انجام خواهد شد. ما توصیه میکنیم پروفایل کردن را اول برای تشخیص سنگین بودن عملیات قبل از پیچیدهتر کردن کد انجام دهید.
آیا باید کامپایلر را امتحان کنم؟
لطفاً توجه داشته باشید که کامپایلر هنوز در حالت بتا قرار داشته و مشکلات زیادی دارد. در حالی که در شرکتهایی مانند متا در محیط عملیاتی استفاده شده است، استقرار کامپایلر در محیط عملیاتی برای برنامه شما به سلامت پایگاه کد شما و چگونگی پیروی شما از قوانین React بستگی دارد.
شما نیازی به عجله برای استفاده از کامپایلر ندارید. تا قبل ازینکه سمت کامپایلر بروید، اشکالی ندارد که تا رسیدن به نسخه پایدار منتظر بمانید. با این حال، ما از کسانی که برای تست از کامپایلر در برنامههایشان استفاده می کنند قدردانی میکنیم، و می توانید با دادن بازخورد به ما، ما را در مسیر بهبود کامپایلر کمک کنید.
شروع به کار
علاوه بر این مستندات، ما شما را برای دریافت اطلاعات و آشنایی بحثهای بیشتر در مورد کامپایلر به بررسی گروه کاری کامپایلر React توصیه میکنیم.
نصب eslint-plugin-react-compiler
کامپایلر React همچنین یک پلاگین ESLint را در اختیارتان قرار می دهد. پلاگین ESLint میتواند به طور مستقل از کامپایلر استفاده شود، به این معنی که حتی اگر از کامپایلر استفاده نکنید، می توانید از پلاگین ESLint استفاده کنید. برای نصب کد زیر را در ترمینال اجرا کنید:
npm install -D eslint-plugin-react-compiler@beta
سپس، آن را به پیکربندی ESLint خود اضافه کنید:
import reactCompiler from 'eslint-plugin-react-compiler'
export default [
{
plugins: {
'react-compiler': reactCompiler,
},
rules: {
'react-compiler/react-compiler': 'error',
},
},
]
یا، در فرمت پیکربندی eslintrc قدیمی:
module.exports = {
plugins: [
'eslint-plugin-react-compiler',
],
rules: {
'react-compiler/react-compiler': 'error',
},
}
پلاگین ESLint هرگونه نقض قوانین React را در ویرایشگر به شما نمایش میدهد. نمایش این نقص ها، به معنی صرف نظر کامپایلر از بهینهسازی آن کامپوننت یا هوک است. این عملی خودخواسته است، و کامپایلر با رد شدن ازین بخش ها به بهینهسازی سایر کامپوننتها در کد شما ادامه دهد.
استقرار کامپایلر دز کدبیس شما
استقرار در پروژههای موجود
کامپایلر برای کامپایل کامپوننتها و هوکهای تابعی که از قوانین React پیروی میکنند، طراحی شده است. همچنین میتواند با عبور از کدهایی که این قوانین را نقض میکند، این نقض ها را مدیریت کند. با این حال، به دلیل ماهیت انعطافپذیر JavaScript، کامپایلر نمیتواند هر نقض ممکن را شناسایی کند و ممکن است با آلارم منفی کاذب کامپایل کد را کند: یعنی، کامپایلر ممکن است به طور تصادفی کامپوننت/هوکی را که قوانین React را نقض میکند کامپایل کند که میتواند منجر به رفتار عجیبی در زمان اجرا شود.
به همین دلیل، برای اعمال موفق کامپایلر بر روی پروژههای موجود، توصیه می کنیم ابتدا آن را بر روی یک دایرکتوری کوچک از کد محصول خود اجرا کنید. این کار را می توانید با پیکربندی کامپایلر برای اجرا بر روی مجموعهای خاص از دایرکتوریها انجام دهید:
const ReactCompilerConfig = {
sources: (filename) => {
return filename.indexOf('src/path/to/dir') !== -1;
},
};
زمانی که از صحت عملکرد اطمینان پیدا کردید، میتوانید دایرکتوری های بیشتری را تحت پوشش کامپایلر قرار دهید و به تدریج آن را به کل برنامه خود گسترش دهید.
استقرار در پروژههای جدید
اگر شما پروژه جدیدی شروع کنید، میتوانید کامپایلر را برای همه کد بیس خود فعال کنید، که رفتار پیشفرض است.
استفاده از کامپایلر React با React 17 یا 18
کامپایلر React بهترین کارایی را با React 19 RC دارد. اگر نمیتوانید به این نسخه روز رسانی کنید، میتوانید بسته اضافی react-compiler-runtime
را نصب کنید که به کد کامپایل شده اجازه میدهد تا بر روی نسخههای قبل از ۱۹ نیز اجرا شود. با این حال، توجه داشته باشید که حداقل نسخه پشتیبانی شده ۱۷ است.
npm install react-compiler-runtime@beta
شما باید target
صحیح را به پیکربندی کامپایلر خود اضافه کنید، جایی که target
معادل نسخه اصلی React ایست که می خواهید نسخه هدف شما باشد:
// babel.config.js
const ReactCompilerConfig = {
target: '18' // '17' | '18' | '19'
};
module.exports = function () {
return {
plugins: [
['babel-plugin-react-compiler', ReactCompilerConfig],
],
};
};
استفاده از کامپایلر بر روی کتابخانهها
کامپایلر React همچنین برای کامپایل کتابخانهها میتواند استفاده شود. از آنجایی که کامپایلر React نیازمند اجرا روی کد منبع اصلی، قبل از هرگونه تغییری روی کد است، کامپایل کتابخانههای مورد استفاده در پایپلاین ساخت برنامه غیر ممکن است. به همین دلیل، ما توصیه میکنیم که نگهدارندگان کتابخانه به طور مستقل کتابخانههای خود را با کامپایلر، کامپایل و آزمایش کنند و کد کامپایل شده را به npm ارسال کنند.
چون کد شما پیشکامپایل شده است، کاربران کتابخانه شما نیازی به فعالسازی کامپایلر برای ممو کردن خودکار ندارند کتابخانه ندارند. اگر هدفگذاری کتابخانه شما برای برنامههایی قدیمی تر از React 19 باشد، باید حداقل target
مورد نظر را ست کرده و react-compiler-runtime
را به عنوان یک وابستگی مستقیم اضافه کنید. بسته runtime از پیادهسازی درست APIها بر اساس نسخه برنامه استفاده خواهد کرد و در صورت نیاز APIهای گمشده را پلیفیل خواهد کرد.
کد کتابخانه معمولاً نیاز به الگوهای پیچیدهتر و استفاده از راه های فرار بیشتری دراد. به همین دلیل، ما توصیه میکنیم که کتابخانه را به اندازی کافی تست کنید تا از هر گونه مشکلی که ممکن است در استفاده از کامپایلر بر روی کتابخانه شما به وجود آید، شناسایی و جلوگیری کنید. اگر به هر گونه مشکلی برخوردید، همیشه میتوانید با استفاداز از راهنمای use no memo
، کامپوننتها یا هوکهای خاص را از این روند مستثنی کنید.
مشابه برنامهها، نیازی به کامپایل صددرصدی کامپوننت ها و هوکهای کتابخانه نیست برای بهرمندی از مزایای آن نیست. نقطه شروع خوب، شناسایی حساسترین بخشهای عملکردی کتابخانه و اطمینان حاصل کردن از اعمال درست قوانین React می تواند باشد، برای این کار میتوانید از eslint-plugin-react-compiler
برای شناسایی قوانین نقض شده استفاده کنید.
استفاده از کامپایلر
استفاده از Babel
npm install babel-plugin-react-compiler@beta
کامپایلر شامل یک پلاگین Babel است که میتوانید از آن در پایپلاین ساخت خود برای اجرای کامپایلر استفاده کنید.
پس از نصب، آن را به پیکربندی Babel خود اضافه کنید. لطفاً توجه داشته باشید کامپایلر باید اول از همه در پایپلاین اجرا شود:
// babel.config.js
const ReactCompilerConfig = { /* ... */ };
module.exports = function () {
return {
plugins: [
['babel-plugin-react-compiler', ReactCompilerConfig], // must run first!
// ...
],
};
};
بسته babel-plugin-react-compiler
باید قبل از سایر پلاگینهای Babel اجرا شود زیرا کامپایلر به اطلاعات منبع ورودی برای تجزیه و تحلیل صحیح نیاز دارد.
استفاده از Vite
اگر از Vite استفاده میکنید، میتوانید پلاگین را به vite-plugin-react اضافه کنید:
// vite.config.js
const ReactCompilerConfig = { /* ... */ };
export default defineConfig(() => {
return {
plugins: [
react({
babel: {
plugins: [
["babel-plugin-react-compiler", ReactCompilerConfig],
],
},
}),
],
// ...
};
});
استفاده از Next.js
لطفاً به برای اطلاعات بیشتر مستندات Next.js مراجعه کنید.
استفاده از Remix
پلاگین vite-plugin-babel
را نصب کرده و پلاگین Babel کامپایلر را به آن اضافه کنید:
npm install vite-plugin-babel
// vite.config.js
import babel from "vite-plugin-babel";
const ReactCompilerConfig = { /* ... */ };
export default defineConfig({
plugins: [
remix({ /* ... */}),
babel({
filter: /\.[jt]sx?$/,
babelConfig: {
presets: ["@babel/preset-typescript"], // if you use TypeScript
plugins: [
["babel-plugin-react-compiler", ReactCompilerConfig],
],
},
}),
],
});
استفاده از Webpack
جامعه لودر Webpack اکنون از اینجا قابل دستری است.
استفاده از Expo
لطفاً به مستندات Expo برای فعالسازی و استفاده از کامپایلر React در برنامههای Expo مراجعه کنید.
استفاده از Metro (React Native)
فریم ورک React Native از Babel از طریق Metro استفاده میکند، بنابراین لطفاً به بخش استفاده با Babel برای مشاهده دستورالعملهای نصب مراجعه کنید.
استفاده از Rspack
لطفاً به مستندات Rspack برای فعالسازی و استفاده از کامپایلر React در برنامههای Rspack مراجعه کنید.
استفاده از Rsbuild
لطفاً به مستندات Rsbuild برای فعالسازی و استفاده از کامپایلر React در برنامههای Rsbuild مراجعه کنید.
عیبیابی
برای گزارش مشکلات، لطفاً ابتدا یک نمونه حداقلی از برنامه دارای مشکل در زمین بازی کامپایلر React ایجاد کرده و سپس آن را بهمراه گزارش باگ خود برای ما ارسال کنید. شما میتوانید مشکلات را در مخزن گیتهاب facebook/react به ما گزارش کنید.
همچنین میتوانید بازخوردهای خود را در گروه کاری کامپایلر React با ما به اشتراک بگذارید. لطفاً به مستند README برای جزئیات بیشتر در مورد پیوستن مراجعه کنید.
کامپایلر چه فرضهایی دارد؟
کامپایلر React فرض میکند که کد شما:
- جاوا اسکریپت معتبر و معنایی است.
- قبل از دسترسی به مقادیر و پراپرتی های nullable/optional، آزمایش میکند که آیا آنها تعریف شدهاند یا خیر (به عنوان مثال، با فعال کردن
strictNullChecks
در TypeScript)، به عبارتیif (object.nullableProperty) { object.nullableProperty.foo }
یا با زنجیرهسازی اختیاریobject.nullableProperty?.foo
. - از قوانین React پیروی میکند.
کامپایلر React میتواند بسیاری از قوانین React را به طور استاتیک تأیید کند و در زمان تشخیص خطا به طور ایمن از کامپایل صرفنظر کند. برای مشاهده خطاها توصیه میکنیم که eslint-plugin-react-compiler را همچنین نصب کنید.
چگونه میتوانم بدانم که کامپوننتهای من بهینهسازی شدهاند؟
با استفاده از React DevTools (v5.0+) و React Native DevTools که پشتیبانی درونی از کامپایلر React دارند. کامپوننتهایی که توسط کامپایلر بهینهسازی شده باشند، در کنارشان نشان "Memo ✨" نمایش داده می شود.
چیزی بعد از کامپایل کار نمیکند
اگر پکیج eslint-plugin-react-compiler را نصب کردهاید، کامپایلر هرگونه نقض از قوانین React را در ویرایشگر شما نمایش خواهد داد. زمانی که این اتفاق میافتد، به این معنی است که کامپایلر از بهینهسازی آن کامپوننت یا هوک صرف نظر کرده است. این کاملاً طبیعی است و کامپایلر میتواند به بهینهسازی سایر کامپوننتها در کد شما را ادامه دهد. شما نباید همه نقضهای ESLint را فوراً برطرف کنید. میتوانید به آرامی به آنها پرداخته و تعداد بیشتری از کامپوننتها و هوکها را بهینهسازی کنید.
با این حال، به دلیل طبیعت انعطافپذیر و پویا جاوا اسکریپت، امکان تشخیص جامع همه موارد وجود ندارد. ممکن است در این موارد باگها و رفتارهای نامتعین مانند حلقههای بینهایت رخ دهند.
اگر اپلیکیشن شما بعد از کامپایل به درستی کار نمیکند و هیچ خطای ESLint را نیز مشاهده نمیکنید، ممکن است کامپایلر کد شما را به درستی کامپایل نکرده باشد. برای تأیید این موضوع، سعی کنید هر کامپوننت یا هوکی را که فکر میکنید ممکن است عامل مشکل باشد را به صورت دستی و با اضافه کردن راهنمای "use no memo"
از چرخه کامپایل خارج کنید
function SuspiciousComponent() {
"use no memo"; // کامپایلر دیگر این کامپوننت را کامپایل نمی کند
// ...
}
استفاده از "use no memo"
یک راه فرار موقت برای کامپایل نشدن کامپوننتها و هوکهاست. این دستورالعمل درست مثل"use client"
، برای استفاده طولانی طراحی نشده است.
اکیدا استفاد از این دستور بجر در موارد ضروری توصیه نمیشود. زمانی که یک کامپوننت یا هوک را از چرخه کامپایل خارج می کنید، تا زمان حذف دستورالعمل، دیگر کامپایل نخواهد شد. این بدان معناست که حتی اگر کد را اصلاح کنید، کامپایلر هنوز هم از کامپایل آن صرف نظر خواهد کرد.
زمانی که مشکل را برطرف کردید، بررسی کنید که حذف دستورالعمل، مشکل را دوباره برمیگرداند. در این صورت گزارش این باگ را با ما به اشتراک بگذارید (میتوانید یک نمونه کوچک شده از کد یا درصورت باز بودن کد منبع، همه آن را با ما به اشتراک بگذارید). برای این کار از زمین بازی کامپالیر React استفاده کنید تا ما بتوانیم مسئله را شناسایی کرده و آن را اصلاح کنیم.
مسائل دیگر
لطفاً به https://github.com/reactwg/react-compiler/discussions/7 مراجعه کنید.