وقتی Next.js دیگه جواب نمیده: درسهای مهاجرت Railway به Vite + TanStack
نویسنده: آرش لطیفی
تیم Railway فرانتاند پروداکشنش رو از Next.js به Vite و TanStack Start برد — بیلد از بالای ۱۰ دقیقه رسید زیر ۲ دقیقه. ببینیم چرا، چطور، و با چی هزینه کردن.
TL;DR — تیم Railway فرانتاند پروداکشنش (بیش از ۲۰۰ روت) رو در دو پولریکوئست و بدون داونتایم از Next.js به Vite + TanStack Start برد؛ بیلدها از بالای ۱۰ دقیقه رسیدن زیر ۲ دقیقه. علت اصلی یه اپ کاملاً کلاینترند (دش و وبسوکت) بود که با مدلِ سرورمحورِ Next.js نمیخوند، نه اینکه Next.js «بد» باشه.
ماجرا از کجا شروع شد
تیم Railway (پلتفرم هاست ابری) پست مفصلی گذاشته درباره اینکه چرا کل فرانتاند پروداکشنشون رو از Next.js برداشتن. نکته جالب اینه که Next.js رو صریحاً تحویین نمیکنن — میگن اون فریمورک سایت رو از صفر به اپی رسوند که میلیونها کاربر ماهانه سرو میکنه. ولی یه ذره ذره داره به ضررشون تمام میشد:
- بیلدها رد شدن از ۱۰ دقیقه. تقریباً نصفش فقط روی مرحله «finalizing page optimization» معطل میشد. برای تیمی که روزی چند بار دیپلوی میکنه، این یعنی مالیات سنگین روی هر تکرار.
- اپشون ذاتاً کلاینترند بود. دش یه رابط stateful غنیه، کانواسش ریلتایمه، همهجا وبسوکت هست. اصلاً از پریمیتیوهای سرورمحور Next.js استفاده نمیکردن و روی Pages Router اَبسترکشن دستساز خودشون رو برای layout و روتینگ ساخته بودن.
- میدونستن App Router این مشکلات رو حل میکنه، ولی نرفتن. چون مدل App Router سرورمحوره و محصولشون عمداً کلایندریو هست؛ یعنی باید حول یه پارادایمی که لازم ندارن همهچیز رو بازسازی میکردن.
اینجا یه نکته مهم برای هر تصمیمگیرنده هست: Railway با Vercel رقیب مستقیمه و بعضیا تو دیسکاشن این رو مطرح کردن، ولی خود پست دلیل فنی میده و اعضای تیم تو HN تأیید کردن که دلیل رقابتی نبوده — «relevant نیست» چون مشکل، بیلدتایم و معماری بود.
دو PR، صفر داونتایم
مهاجرت ۲۰۰+ روت معمولاً ماهها نرمشدن موازی میبره. اونها در دو پولریکوئستش کرد:
- PR اول: حذف هرچی Next.js خاص بود.
next/image،next/head،next/router— هرکدوم یا با API بومی مرورگر جایگزین شد یا با یه گزینه فریمورک-آگنوستیک. این PR هیچ تغییری در فریمورک نداد؛ فقط وابستگی به Next.js رو صفر کرد. - PR دوم: تعویض خود فریمورک. اول همهچیز غیرِ مرتبط با روتینگ از فایلهای صفحه به کامپوننتهای React مجزا استخراج شد، بعد همه روتها از درخت صفحات قبلی تولید شدن. Nitro بهعنوان لایه سرور اضافه شد و
next.config.jsبا کانفیگ Nitro عوض شد — ریدایرکتهای ۵۰۰+، هدرهای امنیتی و قوانین کش همه یهجا جمع شدن. Node APIهایی که Next.js پلیفیلشون رو میداد (مثلBufferوurl.parse) با نسخههای بومی مرورگر جایگزین شدن.
یک صبح یکشنبه مرج شد، تیم تو Discord وارد «واتر روم» شد و همون روز فیکسها آمد. بدون هیچ داونتایمی.
چی گرفتن، چی دادن
| جنبه | قبل (Next.js) | بعد (Vite + TanStack) |
| --- | --- | --- |
| زمان بیلد پروداکشن | بالای ۱۰ دقیقه | زیر ۲ دقیقه |
| روتینگ | Pages Router با هکهای layout | روتینگ تایپسیف + pathless layout روتها |
| سرو کردن تصاویر | next/image | تگ <img> + اپتیمایز تصویر Fastly روی اِج |
| کش asset | باندلهای درشت | چانکهای content-hashed جدا بهازای هر ماژول |
| SEO/ابزارهای جانبی | next-seo، next-sitemap | معادلهای کوچک داخلی |
اون نکته آخر از پست جذابه: چون هر ماژول چانک content-hashed خودش رو داره، یه تغییر تو صفحه billing فقط همون چانک رو invalidate میکنه و کاربر برگشتی «کیلوبایت دانلود میکنه، نه مگابایت».
تناقض جالب: بقیه میگن Turbopack هم همین کارو میکنه
تو دیسکاشن Hacker News، یکی از مهمترین کامنتها این بود: «با Next 16 و Turbopack بیلدهای ما از ۶ دقیقه رسید به ۲ دقیقه.» یه کاربر دیگه هم گفت از Next.js به React Router رفته و دیپلویهاش از ۷-۸ دقیقه رسیده به ۱-۲ دقیقه.
یعنی اعداد مشابه، دو راهحل متفاوت: یکی ماندن + Turbopack، یکی رفتن + Vite. Railway هم خودش تو کامنتهای HN گفت قبلاً Turbopack امتحان کرده بودن. نتیجه عملی برای تو:
- اگه اپت سرورمحوره (کامپوننتهای سرور، ISR، وبلاگ/فروشگاه)، مهاجرت به TanStack منطقی نیست — Next.js 16.4 با Turbopack و Cache Components همون درد بیلد رو ارزونتر حل میکنه.
- اگه اپت دش-مانند و کاملاً کلاینترنده و بیلدهات بالای چند دقیقهان، پست Railway دقیقاً نقشه راهیه که جلوت هست.
وقتی مهاجرت معنی نداره
قبل از هر تصمیمی، خودت رو بذار جای تیم Railway: اونها محصولی داشتن که ۹۰٪ کلاینته. اگه محصول تو SEO-محوره (بلاگ، فروشگاه، لندینگ) یا از Server Actions و use cache استفاده جدی میکنی، مهاجرت یعنی دور انداختن مزیت اصلیت. مطالعه مقایسه رسمی TanStack Start با Next.js هم اینو تأیید میکنه: RSC در Start هنوز آزمایشی و opt-in هست، در حالی که مدل اصلی App Router دقیقاً همینه. حتی تیم TanStack خودش یه پست رسمی «TanStack Start vs Next.js» داره که میگه هرکدوم برای یه جور اپ خوبن — Start برای روتینگ تایپسیف و state در URL، Next.js برای مدل Server Component و ابزارهای یکپارچه تصویر/فونت/متادیتا.
چکلیست تصمیم
- [ ] بیلد پروداکشن رو با
next build --profileیا لاگ CI اندازه گرفتی و دقیقاً میدونی کدوم مرحله زمان میخوره؟ - [ ] روی Turbopack (پیشفرض Next 16) هستی یا هنوز webpack؟ کمهزینهترین فرصت همینه.
- [ ] چند درصد اپت واقعاً به سرور رندر نیاز داره؟ روت به روت فهرست کن.
- [ ] آیا از Server Actions،
use cache، ISR استفاده میکنی؟ اگه بله، مهاجرت تقریباً همیشه یه قدم به عقبشه. - [ ] وابستگیهای
next/*رو فهرست کردی؟ اگه لیست بلنده، هزینه PR اولِ Railway برات سنگینتره. - [ ] یه اسپایک دو روزه با Vite + TanStack Start روی یه روت غیرحیاتی زدی؟ قبل از تعویض فریمورک، نه بعدش.
Q: Next.js 16.4 دیگه بیلدهای سنگین نداره؟
نه، مشکل حل نشده — ابزار عوض شده. Turbopack از 16 پیشفرضه و چند کاربر HN کاهش از ۶-۷ دقیقه به حدود ۲ دقیقه گزارش کردن. ولی اگه بیلدت هنوز با Turbopack هم بالای چند دقیقهان و اپت کلاینترند، بحث مهاجرت بجاست.
Q: TanStack Start آماده پروداکشنه؟
طبق مستندات رسمی، الان تو مرحله Release Candidate است: APIها «feature-complete و پایدار» معرفی میشن ولی هنوز v1 نشده و لبههای خام داره. Railway با چشم باز این رو پذیرفته و خودش به Vite و TanStack اسپانسر میده.
Q: برای فروشگاه یا سایت شرکتی هم این مسیر منطقیه؟
معمولاً نه. سایتای SEO-محور به SSR و ISR و یکپارچگی تصویر/متادیتای Next.js وابستهان، و پست Railway دقیقاً برعکسشه — یه دش کلاینترند. اونجا که ممکنه سراغ Vite/TanStack بری معمولاً اپهای داخلی و ابزاریه، نه سایت عمومی.