اکوسیستم React همیشه در حال پیشرفت است؛ از قابلیتهایی مانند Server Components و Concurrent Rendering گرفته تا ابزارهای جدیدی که با هدف بهبود تجربه توسعهدهندگان و کاربران ساخته میشوند.
اما یک موضوع همچنان اهمیت زیادی دارد: چگونه میتوان یک اپلیکیشن React ساخت که بدون قربانی کردن تجربه توسعه، JavaScript کمتری به مرورگر ارسال کند؟
یکی از پروژههایی که اخیراً با همین هدف توجه زیادی جلب کرده، TanStack Redact است؛ یک Runtime جایگزین برای React که تلاش میکند با حفظ APIها، کامپوننتها و Hookهای آشنای React، حجم Runtime سمت مرورگر را کاهش دهد.
در این مقاله بررسی میکنیم Redact دقیقاً چیست، چگونه کار میکند، چه تفاوتی با React دارد و آیا استفاده از آن در پروژههای واقعی ارزشمند است یا خیر.
TanStack Redact یک Runtime جایگزین برای اپلیکیشنهای React است که با هدف ارائه پیادهسازی کوچکتر و سادهتر از React و React DOM توسعه داده شده است.
نکته مهم این است که Redact یک Framework جدید یا جایگزین کامل اکوسیستم React نیست. این پروژه تلاش میکند همان مدل کامپوننتمحور و APIهای React را با یک پیادهسازی متفاوت در اختیار توسعهدهندگان قرار دهد.
به کمک Redact میتوان همچنان از موارد زیر استفاده کرد:
- Function Components
- React Hooks
- Context API
- Refs
- Memoization
- Lazy Components
- Portals
- Error Boundaries
- Suspense
- Server-Side Rendering و Hydration
یکی از ویژگیهای مهم این پروژه، عدم نیاز به تغییر گسترده در کدهای اپلیکیشن است. میتوان همچنان از Importهای آشنای React استفاده کرد و با تغییر تنظیمات Build، Runtime مرورگر را به Redact سپرد.
برای مثال، کد زیر بدون تغییر در مدل برنامهنویسی قابل استفاده است:
import { useState } from 'react'
function Counter() {
const [count, setCount] = useState(0)
return (
<button onClick={() => setCount((count) => count + 1)}>
Clicked {count} times
</button>
)
}
export default Counter
این یعنی هدف Redact بازنویسی اپلیکیشنهای React نیست؛ بلکه تغییر بخشی از زیرساخت اجرای آنهاست.
React یک اکوسیستم قدرتمند و بالغ است و طبیعی است که با گذشت زمان قابلیتهای بیشتری به آن اضافه شوند.
اما تمام اپلیکیشنها به تمام قابلیتهای Runtime React نیاز ندارند.
برای مثال، مکانیزم Concurrent Rendering، زمانبندی اولویتدار و قابلیت متوقف کردن و ادامه دادن Render، برای برخی اپلیکیشنها بسیار مفید است؛ اما پیادهسازی این قابلیتها هزینه پیچیدگی و حجم بیشتری هم دارد.
Redact با یک رویکرد متفاوت توسعه پیدا کرده است:
بهجای پیادهسازی تمام رفتارهای React، روی رفتارهایی تمرکز میکند که اپلیکیشنها و وابستگیهایشان واقعاً به آنها نیاز دارند.
در نتیجه، Redact از Rendering همگام یا Synchronous Rendering استفاده میکند و به سراغ مدل Time Slicing و Interruptible Rendering در React نمیرود.
این تصمیم باعث میشود پیادهسازی Runtime کوچکتر شود؛ البته به این معنی نیست که Redact در تمام شرایط سریعتر از React خواهد بود.
یکی از نکات جالب Redact این است که نحوه استفاده از آن به Framework و ابزار Build پروژه بستگی دارد.
این پروژه با موارد زیر یکپارچگی دارد:
- TanStack Start
- Vite
- Vinext
- Next.js
در پروژههای Vite و TanStack Start، Redact میتواند Runtime رندر سمت سرور و مرورگر را مدیریت کند.
اما در Next.js و Vinext معماری متفاوت است:
Next.js Application
|
React Server Runtime
|
HTML + RSC Payload
|
Browser
|
Redact Runtime
|
Client Rendering
& Hydration
در این معماری، React همچنان مسئول Server Rendering و Server Components است؛ در حالی که Redact مسئول Hydration و اجرای کامپوننتهای سمت کلاینت خواهد بود.
همچنین Routing، Caching و انتقال Server Actions همچنان در اختیار Framework باقی میمانند.
این موضوع اهمیت زیادی دارد؛ زیرا Redact قرار نیست مسئولیتهای Next.js یا معماری Server Components را جایگزین کند.
یکی از جذابترین بخشهای معرفی Redact، مقایسه حجم خروجی Build با React است.
طبق اندازهگیری منتشرشده توسط تیم TanStack، یک اپلیکیشن یکسان با React و Redact در Frameworkهای مختلف Build شده و حجم تمام فایلهای JavaScript و CSS سمت کلاینت پس از فشردهسازی Gzip مقایسه شده است.
| Framework | React | Redact | کاهش حجم |
|---|
| TanStack Start | 109.3 KB | 62.3 KB | 43% |
| Vite | 68.3 KB | 20.1 KB | 70.5% |
| Vinext | 138.1 KB | 98.8 KB | 28.5% |
| Next.js | 175.6 KB | 139.9 KB | 20.4% |
این اعداد مربوط به یک اپلیکیشن آزمایشی مشخص هستند و تضمین نمیکنند که همین درصد کاهش را در تمام پروژهها تجربه کنید.
همچنین این اندازهها مجموع خروجی Client JavaScript و CSS، شامل Lazy Chunks هستند؛ نه حجم دانلود یک صفحه مشخص.
منبع اندازهگیریها:
Introducing TanStack Redact
شاید در نگاه اول کاهش Bundle Size مهمترین تفاوت این دو باشد، اما تفاوت اصلی در مدل اجرای آنهاست.
React از یک Concurrent Scheduler استفاده میکند که امکان اولویتبندی کارها، متوقف کردن Render و ادامه آن در زمان مناسب را فراهم میکند.
در مقابل، Redact از Rendering همگام استفاده میکند.
این تفاوت چه تأثیری دارد؟
فرض کنید یک کامپوننت در حال پردازش یک لیست بزرگ یا اجرای یک محاسبه سنگین است.
در React، Scheduler میتواند در شرایط مناسب اجرای کار را متوقف کند تا مرورگر فرصت رسیدگی به کارهای مهمتر را داشته باشد.
اما در Redact، عملیات Render به شکل همگام انجام میشود و یک Render سنگین میتواند باعث تأخیر در پاسخگویی به ورودی کاربر شود.
البته این به معنی نبود کامل قابلیت Transition در Redact نیست.
Redact از برخی رفتارهای مرتبط با Suspended Transitions، Pending State و Optimistic Updates پشتیبانی میکند؛ اما این قابلیتها به معنی داشتن Concurrent Scheduler کامل React نیستند.
بنابراین انتخاب بین این دو باید با توجه به نیاز واقعی اپلیکیشن انجام شود.
یکی از مزیتهای Redact این است که نیازی به تغییر Importهای React در فایلهای پروژه ندارید.
ابتدا پکیج را نصب کنید:
pnpm add @tanstack/redact
سپس فایل vite.config.ts را به شکل زیر تنظیم کنید:
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { redact } from '@tanstack/redact/vite'
export default defineConfig({
plugins: [
react(),
redact(),
],
})
همانطور که مشاهده میکنید، همچنان از @vitejs/plugin-react استفاده میشود و Redact در کنار آن قرار میگیرد.
بعد از این تغییر، میتوانید Importهای قبلی خود را حفظ کنید:
import { useState, useEffect } from 'react'
import { createRoot } from 'react-dom/client'
پلاگین Redact وظیفه جایگزینی Runtime را در Build بر عهده میگیرد.
نکته: قبل از استفاده در محیط Production، راهنمای Integration و Compatibility را بررسی کنید و تستهای پروژه را اجرا کنید.
راهنمای رسمی:
Redact + Vite
اگر پروژه شما با Next.js توسعه داده شده، میتوانید از Integration رسمی Redact استفاده کنید.
فایل next.config.mjs:
import { withRedact } from '@tanstack/redact/next'
export default withRedact({})
با این تنظیمات، Redact در Browser Runtime استفاده میشود و React همچنان مسئول رندر سمت سرور و Server Components خواهد بود.
نکته مهم این است که این Integration برای App Router و Pages Router در نظر گرفته شده و از تنظیمات Bundler پشتیبانیشده در مستندات پروژه استفاده میکند.
راهنمای رسمی:
Redact + Next.js
خیر. کاهش حجم Runtime بهتنهایی برای انتخاب یک ابزار کافی نیست.
Redact مزایای مهمی دارد، اما محدودیتهایی هم دارد که باید قبل از مهاجرت در نظر گرفته شوند.
مزایا:
- کاهش حجم Runtime سمت کلاینت
- حفظ ساختار آشنای React
- عدم نیاز به تغییر گسترده Importها
- پشتیبانی از Integrationهای مختلف
- امکان استفاده از بسیاری از APIهای React
- مناسب برای پروژههایی که کاهش JavaScript دریافتی مرورگر برایشان اهمیت دارد
محدودیتها و نکات قابل توجه:
- عدم پشتیبانی از Concurrent Rendering و Time Slicing به شکل React
- تفاوت برخی رفتارهای APIها با React
- نیاز به بررسی سازگاری کتابخانههای Third-Party
- امکان کند شدن پاسخگویی رابط کاربری در Renderهای سنگین
- ضرورت اجرای تستهای واقعی در پروژه، بهخصوص برای Hydration، Suspense و Forms
برای مثال، قابلیت Feature Flags در Redact اجازه میدهد برخی ویژگیهای اختیاری را غیرفعال کنید؛ اما غیرفعال کردن هر Feature میتواند رفتار مشخصی را از Runtime حذف کند.
به همین دلیل بهتر است ابتدا با تنظیمات پیشفرض شروع کنید و فقط قابلیتهایی را غیرفعال کنید که مطمئن هستید پروژه و وابستگیهای آن به آنها نیازی ندارند.
به نظر من، Redact را نباید بهعنوان جایگزین قطعی React در نظر گرفت.
React همچنان انتخاب اصلی و بالغ اکوسیستم است و برای اپلیکیشنهایی که به Concurrent Features وابستگی زیادی دارند، انتخاب مطمئنتری محسوب میشود.
در مقابل، Redact گزینه جذابی برای پروژههایی است که میخواهند از APIها و اکوسیستم React استفاده کنند، اما حجم JavaScript سمت کلاینت را کاهش دهند.
پیشنهاد من این است:
- ابتدا Bundle Size فعلی پروژه را با ابزارهایی مثل
rollup-plugin-visualizer بررسی کنید.
- یک Branch جداگانه برای آزمایش Redact ایجاد کنید.
- Build تولیدی را با نسخه React مقایسه کنید.
- Hydration، Navigation، Forms، Suspense و Third-Party Components را تست کنید.
- در نهایت روی صفحات سنگین و تعاملات واقعی اپلیکیشن Performance را اندازهگیری کنید.
فراموش نکنید که کاهش Bundle Size لزوماً به معنی بهبود تمام معیارهای تجربه کاربر مانند INP، LCP یا سرعت Hydration نیست.
TanStack Redact یکی از پروژههای جالب اکوسیستم React است که با یک ایده مشخص سراغ بهینهسازی Runtime رفته است: حفظ تجربه توسعه با React، در کنار ارسال JavaScript کمتر به مرورگر.
نکته مثبت آن این است که برای استفاده از Redact لازم نیست معماری کامپوننتها و Hookهای پروژه خود را از ابتدا بازنویسی کنید.
با این حال، تفاوت در مدل Rendering و نبود Concurrent Scheduler کامل React باعث میشود که این ابزار برای همه اپلیکیشنها انتخاب مناسبی نباشد.
به نظرم ارزش واقعی Redact در این است که به توسعهدهندگان اجازه میدهد انتخاب بیشتری در مورد Runtime اپلیکیشنهای React داشته باشند.
بهجای اینکه صرفاً به اعداد Benchmark اعتماد کنیم، بهتر است آن را در یک پروژه واقعی امتحان کنیم و نتیجه را با معیارهای قابل اندازهگیری بسنجیم.