Next 16 va React 19 ga ko'chish: nima buzildi, nimani pin qildim
Saytimni bir yildan beri Next 15 va pnpm bilan olib borayotgan edim. Muammo frameworkda emas edi — har safar loyihaga qaytganimda nvm va pnpm bir-biri bilan urishardi, corepack goh ishlaydi, goh yo'q, CI'da esa boshqa Node versiyasi chiqib qolardi. Bu texnik qarz emas, shunchaki har kuni tishlaydigan mayda tosh edi.
Shuning uchun Next 16 chiqqanda ko'chishni bahona qildim va bir yo'la butun muhitni almashtirdim: paket menejeri, framework, React versiyasi va stil tizimi. Aytishim kerak — bu tavsiya emas, xavfli qadam. Meni qutqargan narsa uni uchta alohida pull requestga bo'lganim bo'ldi.
Birinchi qaror: Bun'ga to'liq o'tish
Bun'ni ilgari faqat backendda (Hono bilan) ishlatardim. Bu safar frontendga ham olib kirdim va natija kutganimdan yaxshi chiqdi: nvm bilan raqs tugadi, bun install sekundlarda tugaydi, skriptlar bun run dev va bun run build bilan oddiy ishlaydi.
Muhim tafsilot — package.json da paket menejerini aniq belgilab qo'yish kerak, aks holda CI eski odatiga qaytadi:
{
"packageManager": "bun@1.3.14",
"scripts": {
"dev": "bun --bun next dev",
"build": "bun --bun next build"
}
}bun --bun prefiksi muhim: usiz Bun shunchaki Node'ni chaqiradi va siz Bun runtime'ini emas, faqat uning paket menejerini ishlatgan bo'lasiz.
Vercel tomonida esa bitta qator yetdi:
{
"bunVersion": "1.x"
}Bu hali Public Beta, shuning uchun o'zim uchun chekinish yo'lini oldindan yozib qo'ydim: muammo chiqsa shu qatorni o'chiraman va build Node'da davom etadi. Migratsiyada har bir yangi narsaning yonida shunday bir qatorlik "orqaga qaytish" rejasi bo'lishi kerak.
Next 16: middleware o'ldi, proxy tug'ildi
Eng ko'zga tashlanadigan o'zgarish — middleware.ts endi proxy.ts. Faqat nomi emas, joylashuvi ham: menda u src/proxy.ts ga ko'chdi. Ichidagi mantiq deyarli o'zgarmadi, men uni til (x-locale) headerini o'rnatish uchun ishlataman.
Asl mehnat esa boshqa joyda edi: `params` va `headers()` endi asinxron. Ya'ni har bir sahifa va har bir metadata generatori tegishli:
export default async function Page({
params,
}: {
params: Promise<{ lang: string; slug: string }>
}) {
const { lang, slug } = await params
// ...
}Bu mexanik ish, lekin ko'p joyni qamraydi va TypeScript uni to'liq tutib beradi — shuning uchun eng yaxshi strategiya bun run build ni yurgizib, kompilyator ko'rsatgan xatolar ro'yxati bo'yicha yuqoridan pastga tushish bo'ldi.
Build endi standart holda Turbopack bilan ketadi. Men uchun bu asosan tezlik farqi bo'ldi, hech narsa buzilmadi.
React 19: kutganimdan osonroq
Rostini aytsam, eng ko'p qo'rqqanim shu qadam edi. Amalda esa deyarli hech narsa qilishim kerak bo'lmadi. Sabab oddiy: loyihamda sinf komponentlari, eski context API va propTypes yo'q edi. React 19 ni og'riqli qiladigan narsalar aynan o'shalar.
Bundan bitta amaliy xulosa chiqadi: React versiyasini ko'tarish qanchalik og'riqli bo'lishi versiyaning o'zidan emas, sizning kodingiz qanchalik eski patternlarga tayanganidan kelib chiqadi.
Eng ko'p vaqt olgan narsa: TypeScript'ni pin qilish
Mana shu joyda men bir kun yo'qotdim.
TypeScript 7 chiqqan — Go'da qayta yozilgan, sezilarli tez kompilyator. Tabiiyki uni o'rnatdim. Va lint darhol ishdan chiqdi: typescript-eslint hali TS 7 ni qabul qilmaydi, uning peer talabi <6.1.0.
Tanlov shunday turdi: tez kompilyatsiya yoki ishlaydigan lint. Men lintni tanladim va versiyani qat'iy pin qildim:
{
"devDependencies": {
"typescript": "6.0.3"
}
}^ belgisi ataylab yo'q. Caret bo'lsa keyingi bun install meni yana o'sha teshikka olib tushardi.
Bu holat migratsiyalardagi eng ko'p uchraydigan tuzoqni yaxshi ko'rsatadi: sizni framework emas, ekotizim ushlab qoladi. Yangi versiya chiqqani bilan uning atrofidagi plaginlar, linterlar va tip paketlari hali yetib kelmagan bo'ladi. Shuning uchun migratsiyani rejalashtirganda "asosiy paket chiqdimi?" emas, "men tayanadigan plaginlar chiqdimi?" deb so'rash kerak.
Yo'l-yo'lakay tozalash
Katta migratsiya — bog'liqliklarni tozalash uchun eng yaxshi payt, chunki siz allaqachon hamma narsani qayta sinab chiqyapsiz. Men uchtasini butunlay olib tashladim: daisyui, autoprefixer va @eslint/eslintrc. Birinchisi endi kerak emas, ikkinchisini Tailwind 4 o'zi bajaradi, uchinchisi esa ESLint'ning eski konfiguratsiya formatiga ko'prik edi.
Yana bitta narsa postcss bilan bog'liq bo'ldi. Next o'zi bilan 8.4.31 versiyasini olib keladi, unda esa ma'lum zaiflik bor (GHSA-qx2v-qp2m-jg93). Yechim — bog'liqlikni majburan ko'tarish:
{
"overrides": {
"postcss": "^8.5.10"
}
}Bunday overrides yozuvlarini men har doim izoh bilan qoldiraman — nima uchun kiritilganini olti oydan keyin hech kim eslamaydi, keyin esa "nega bu bor ekan?" deb o'chirib yuboriladi.
Stil tizimi ham shu migratsiyada Tailwind 4 ga o'tdi, lekin u alohida katta mavzu — konfiguratsiya fayli butunlay yo'qoladi va hamma narsa CSS ichiga ko'chadi. Uni keyingi maqolada batafsil yozaman.
Nimani boshqacha qilardim
Deyarli hech narsani. Yagona to'g'ri qarorim — hammasini bitta "katta migratsiya" PR'iga tiqmaganim bo'ldi. Uchta alohida PR: birinchisi runtime va paket menejeri, ikkinchisi framework va React, uchinchisi stil va lint. Har birini alohida deploy qilib, alohida tekshirdim.
Agar hammasi bitta PR bo'lganda va build sinsa, men "nima buzdi?" degan savolga javob topolmasdim — chunki bir vaqtning o'zida to'rtta o'zgaruvchi almashgan bo'lardi.
Migratsiyani boshlayotgan bo'lsangiz tartib shunday bo'lsin: avval muhit (runtime, paket menejeri), keyin framework, oxirida ko'rinish qatlami. Har qadamdan keyin build va deploy. Va har bir yangi narsa yoniga bitta qatorlik chekinish rejasini yozib qo'ying — u kerak bo'lmasligi mumkin, lekin kerak bo'lganda sizni yarim tundan qutqaradi.