از Next.js 15 اینها را بردار؛ عدد تبلیغاتی Turbopack را قول ندان
Next.js 15 برای من یک جهش شخصیتی نبود. یک مجموعه تصمیم بود که بعضیشان کار هر روز را روانتر میکنند و بعضیشان عادت نسخه قبل را میشکنند. اگر فقط جمله «پایدار و آماده پروداکشن» را خواندهای، هنوز نمیدانی کدام شکست در ارتقای تو واقعی است.
نسخه را از روی وبلاگ سال عرضه قضاوت نکن. lockfile را بخوان. در زمان عرضه، App Router با React 19 همتراز شد و Pages Router میتوانست روی React 18 بماند تا وقتی خودت آماده ارتقا هستی. React Compiler آزمایشی بود. `after` هم در آن مقطع بهصورت `unstable_after` معرفی شد، برای کاری بعد از تمام شدن استریم پاسخ. اگر امروز نسخهات این API را پایدار کرده، مرزش عوض نشده: کار بعد از پاسخ، نه کار داخل پاسخ.
Turbopack را برای dev بخواه، نه بهجای معماری
`next dev --turbo` در این خط پایدار شد. دلیل فنیای که تیم میگوید ساده است: Turbopack کار را روی چند CPU پخش میکند، در حالی که در webpack عمدتاً تبدیل TypeScript و JavaScript با SWC موازی بود. روی ماشین چند هستهای این در عمل حس میشود، بهخصوص شروع سرور توسعه و Fast Refresh.
Vercel روی اپ خودش شروع سرور توسعه و بهروزرسانی کد را خیلی سریعتر از قبل گزارش کرد. این را اندازه اپ آنها بدان، نه قول برای ریپوی تو. اگر پروژه کوچک است، تفاوت ممکن است ناچیز باشد. اگر پروژه بزرگ است و هنوز روی webpack در dev میمانی، یک شاخه با پرچم turbo ارزش یک روز کار را دارد. پروداکشن را با همین پرچم قاطی نکن. برد اینجا بازخورد توسعه است.
اگر ارتقا فقط به خاطر این سرعت باشد و مسیر درخواست هنوز دینامیک تصادفی است، قهوه کوتاهتر میشود و صفحه کاربر همان قدر منتظر میماند.
درخواست را ناهمگام کن چون رندر نباید گروگان کوکی بماند
APIهایی که به داده خاص درخواست وابستهاند، مثل `cookies` و `headers` و `params` و `searchParams`، در این خط ناهمگام شدند. شکل قدیمی که اینها را همزمان میخواند باید برود. codemod با `@next/codemod` بخش مکانیکی را کم میکند. فهم را کم نمیکند.
دلیلش این است که در رندر سمت سرور، همهچیز به درخواست وابسته نیست. اگر خواندن کوکی در ریشه درخت باشد، بخشی از صفحه که میتوانست زودتر آماده شود هم منتظر میماند. ناهمگام شدن این APIها صحنه را برای جدا کردن آن کار میچیند. اگر همهجا `await cookies()` را در layout ریشه کپی کنی، فقط سینتکس را نو کردهای و همان گروگانگیری سر جایش است.
موقع ارتقا، دنبال جایی بگرد که این خواندن واقعاً لازم است. صفحه حساب لازمش دارد. صفحه بازاریابی اغلب نه.
کش پیشفرض خاموش، قابل پیشبینیتر از کش پیشفرض روشن است
برای GET در Route Handler و برای Client Router Cache، پیشفرض از کششده به کشنشده عوض شد. اگر رفتار قبلی را میخواهی باید صریح opt-in کنی. این برای کسی که به کش جادویی عادت داشت درد است. برای کسی که باگ محتوای کهنه را دیباگ کرده، قابل توضیحتر است.
سیاست را کنار داده بنویس. صفحه عمومی پایدار را کش کن و بگو کدام نوشتن باطلش میکند. داده مجوزدار را پیشفرض تازه بگذار. «همهجا کش» و «هیچجا کش» هر دو تنبلیاند، فقط جهت تنبلی فرق میکند.
اگر خودت میزبانی میکنی، کنترل بیشتر روی هدر `Cache-Control` در همین خط به کارت میآید. روی پلتفرم مدیریتشده، هدر را با رفتار CDN همان پلتفرم یکی کن و دو لایه کش متناقض نساز.
در توسعه، نشانگر مسیر ایستا یا دینامیک را جدی بگیر. خیلی وقتها یک خواندن کوچک، صفحهای را که فکر میکردی ایستاست دینامیک میکند. دیدن این در dev ارزانتر از حدس زدن در پروداکشن است.
فرم، پیکربندی، و کار بعد از پاسخ
`next/form` فرم HTML را با ناوبری سمت کلاینت همراه میکند. جای هر فرم سنگین با کتابخانه وضعیت نیست. جای فرمی است که ارسال باید ساده بماند و کاربر را تمامصفحه بازنشانی نکند. اگر اعتبار چندمرحلهای و وضعیت غنی داری، این کامپوننت مسئلهات را حل نمیکند. فقط مرز را قاطی نکن.
`next.config.ts` یعنی پیکربندی را با همان تایپی بنویسی که بقیه اپ را. اشتباه اسم گزینه در فایل پیکربندی از آن دسته باگهایی است که دیر و در سکوت ظاهر میشود. تایپ اینجا لوکس نیست.
`after` برای لاگ، آنالیتیکس، و تمیزکاری است که نباید پاسخ کاربر را معطل کند. برای بهروزرسانی که کاربر باید در همان پاسخ ببیند مناسب نیست. اگر کار بعد از پاسخ شکست بخورد، کاربر نباید خیال کند عمل اصلی انجام نشده، و تو هم نباید خیال کنی آن کار حتماً دیده شده. مشاهدهپذیری این شاخه جدا از وضعیت HTTP است.
`instrumentation.js` در این خط از آزمایشی به پایدار رسید. قلاب چرخه حیات سرور برای tracing و مانیتورینگ اینجاست. ابزار را اینجا وصل کن، نه با وصله پراکنده در هر Route Handler.
امنیت Server Action و بقیه ارتقا
شناسه Server Action حدسزدنی نیست و اکشن استفادهنشده از باندل پروداکشن حذف میشود. این سطح حمله را کوچک میکند. جایگزین مجوز نیست. اکشن همچنان باید بداند چه کسی اجازه آن جهش را دارد. حذف اکشن مرده خوب است. اعتماد به «کسی URL را نمیداند» کافی نیست.
پشتیبانی ESLint 9 هم در همین نسل آمد. اگر هنوز پیکربندی تخت را برنداشتهای، فریمورک در ارتقا میتواند با `ESLINT_USE_FLAT_CONFIG=false` راه فرار بگذارد تا مهاجرت lint همزمان با مهاجرت فریمورک قفل نشود. از این راه فرار استفاده کن، ولی آن را مقصد ندان.
برای پروژه تازه، شروع روی این خط یا جدیدتر منطقی است، به شرطی که سند همان نسخه نصبشده را بخوانی نه پست قدیمی را. برای پروژه زنده، اول روی شاخه با codemod برو، تست مسیرهایی را بگیر که کوکی، params، و فرم دارند، و رفتار کش را عمداً انتخاب کن. سرعت Turbopack در dev جای این مرور را نمیگیرد.
React Compiler را در پروداکشن از روی کنجکاوی سراسری روشن نکن. وعدهاش کم شدن `useMemo` و `useCallback` دستی است. تا وقتی روی سطح محدود اندازهنگرفتهای، بهینهسازی خودکار را فرض نکن.
پرسشهای کوتاه
باید فردا همه اپها را به ۱۵ ببرم؟ اگر روی خط نگهداری قدیمی و بدون مسیر ارتقا ماندهای، بله بهصورت برنامهریزیشده. اگر وسط ویژگی هستی، شاخه جدا با codemod و تست مسیر دینامیک، نه ارتقای قاطی با بازنویسی UI.
کش پیشفرض خاموش یعنی دیگر کش نکنم؟ یعنی دیگر فرض نکن فریمورک برایت کش کرده. جایی که داستان باطلسازی داری روشن کن.
`after` را برای ایمیل تراکنشی بگذارم؟ فقط اگر شکستش را جدا میبینی و کاربر به موفق بودن آن ایمیل در همان پاسخ تکیه ندارد. کار قابل مشاهده محصول را پشت کاری که بعد از پاسخ میرود قایم نکن.