React17 dan 18 ga update qilamiz
Qanday qilib react 17dan 18ga update qilganim, jarayondagi muammolar va kelajakda bu ishni qilmoqchi bo'lganlarga tiplar.
Bu usullarni react kutubxonasini yangilash misolida ko'rib chiqamiz lekin berilgan maslahatlar javascript ekosistemasidagi boshqa paketlarni yangilash uchun ham foyadli bo'ladi.
Motivation: Texnologiyalar qanchalik tez yangilanib, o'zgarib borgani bilan, uzoq muddatdan beri mavjud bo'lgan proektlarga ishga kirsangiz yuqori ehtimol bilan ozgina eskiroq toolinglar yoki librarylar bilan ishlashga majbur bo'lasiz bazida. Ayniqsa JavaScriptda har oyda yangi freymwork chiqib turganda, entuziastlar ham bazida charchaydi va ko'zga ko'rinarli darajada o'zgarish bo'lmasa shunchaki yangilanishlarni ortga suradi. Ishga kirgan joyingizda sizga texnologialarni yangilash yuklatilsa bu juda yaxshi tajriba bo'ladi lekin shu bilan birga qiyinchiliklar ham keltirib chiqarishi mumkin. Yaqinda shunday updateni amalga oshirdim va internetda bu haqdia malumot men tasavvur qilgandan ancha kam ekanligini sezdim.
Nega bu mavzuda tutoriallar kam yoki yetarlicha chuqur emas?
Hammaning proektlari farq qiladi, ayniqsa anchadan beri development qilib kelinyotganlari. Shuning uchun bir proekt uchun ishlagan usul boshqasi uchun ishlamasligi yoki umuman to'gri kelmasligi mumkin. Shuni sezgan holda ko'pchilik bu mavzuda yozmaydi yoki yozsa ham npm i react@18
dan deytarli uyog'iga o'tmaydi. Ushbu postdagi strategiya va maslahatlarni nafaqat react balki deyarli barcha kutubxonalarni yangilashda ishlatishingiz mumkin. Aynan bir muammoni qanday yechishni emas o'xshash muammoar kelib chiqsa qanday yondoshishni eslab qolish uchun foydali post deb o'ylayman.
Boshlashdan oldin kichik tiplar.
Release notes o'qishni o'rganing. Aynan release notesda siz ishlatmoqchi/yangilamoqchi bo'lgan kutubxonalarga kiritilgan o'zgarishlar yoziladi. Osonlik bilan har bir versiyada nimalar o'zgarganini ko'rishingiz mumkin.
Yangilamoqchi bo'lgan kutubxonangizni versioning strategiyasi bilan tanishib chiqing va albatta release notelarini o'qib o'zingiz muammolarsiz (minimal breaking changelar bilan) update qilib ishlata oladigan versiyaga yangilang. Har bir kutubxonani eng ohirgi versiyaga yangilash shart emas.
npm ls [some-lib]
komandasi. Bu komanda bilan sizdagi qaysi paketlar ushbu (some-lib) libraryni anyan qaysi versiyasini ishlatayotganini ko'ra olasiz va bu sizga reactni yangilagandan keyin yana qaysi liblarni yangilash kerakligini tushunishga yordam beradi.Proektni copy qilib boshqa biror directory (papka)ga o'tkazib oling. Va albatta yangi branch ham kerak. Sababi, update qilayotgan vaqtinginzda boshqa vazifalar yoki bugfixlar qilish kerak bo'lib qolsa har safar commit qilib, qaytada npm install qilishga to'gri kelmaydi.
Nimadan boshlaymiz?
Bizga bu yangilanish rostdan ham kerakligi va resurslarni hisoblashdan.
A) Agar sizga reactni yangilash vazifasini yuklatishmagan bo'lsa lekin siz buni kerak deb hisoblasangiz, unda buni avvalambor yuqoridagilarga senior dasturchilar va leadlarga isbotlashingiz kerak. Prioritetlarni to'gri qo'ying, foydalanuvchilar sizga reactni malum varsiyasini ishlatganingiz uchun emas dastur foydali bo'lgani uchun pul to'lashadi. Texnik ishlarni holatga qarab biznes topshiriqlaridan keyinga surgan maqul. Biznes vazifalar kamayganda esa bunday idealar uchun menejmentdan ruxsat olish ham oson bo'ladi. Menda shunday holat edi, o'zim tashabbus qilib reactni yangilaylik dedim va quyida men ko'rsatgan sabablar.
React 18 batchingni yanada yaxshilaydi. Bu esa kamroq re-renderlarga sabab bo'ladi. Bizda ko'p murakkab table va biznes logikalar borligi sabab bunday yangilanish bizga yaqqol foyda beradi.
Proektda deyarli har doim memoizatsiyalangan kod yozamiz. To'gri memoizatsiya qila olish va uni muammolarini debug qilish anchagina vaqt oladi. React 18 esa 19 ga bo'lgan eng katta qadamlardan. Qachondir React19 ga o'ta olsak boshqa qo'l bilan memoizatsiyalash kerak bo'lmaydi bu esa buglarni kamaytiradi va yangi featurelarni ishlab chiqishga ketadigan vaqtni sezilarli tezlashtiradi.
B) Agar sizga bu vazifa allaqachon yuklatilgan bo'lsa bu yaxshi. Davom etaveramiz.
Reactni yangilashdan avval
Ishlatayotgan UI va boshqa reactga bevosita bog'langan librarylarni tekshirib chiqing. Ular React 18ga update qilishganmi. Bazida UI liblarni ham React versiyasini support qiladigan versiyasiga yangilashga to'gri keladi. Bu jarayonda esa UI liblar breaking changelar qilishgan bo'lishi mumkin. Shunday bo'lsa bu changelarni aniqlab, analiz qilib update imkoni bormi yoki yo'qligini va ular kiritgan o'zgarishlarni kod bazangizga olib kirish uchun ketadigan vaqtni qayta ko'rib chiqing.
Tooling. Proektingiz eskiroq bo'lgani uchun odatda faqat Reactni yangilash kamlik qiladi.
Eng yaqqol toolingda yangilash kerak bo'lgan narsalardan biri react-hot-loader. Bu kutubxona hozirda arxivlangan va uni o'rniga react-refresh ishlatish tavsiya qilinadi. Biz webpack ishlatamiz va hot reloaderni o'rnini react-refresh-webpack-plugin bilan amlashtirish menga unchalik qiyin bo'lmadi. Plugin dokumentatsiyasi yaxshi yozilgan. Siz ham o'z compiler/bundleringizga qarab react refreshni yoki uni ustiga qurilgan pluginlarini o'rnatishingiz mumkin.
Eslint. Yuqorida aytgan
npm ls
komandasi bilan topdimki bizdagieslint-plugin-react
vaeslint-plugin-react-hooks
librarylarimiz React18ni qo'llab quvvatlamas ekan. Ularni ham release notelarni o'qib eng ohirgi React18ni support qiladigan lekin hechnimani buzib qo'ymaydigan versiyaga ko'tardim. Sizda bunday kutubxonalar ko'proq yoki kamroq bo'lishi mumkin.
Types. React18 tipizatsiyaga bazi breaking changelar olib kiradi. Bular:
Type definitionlar. Type definitionlarni yangilayotganda ham hohlagan ohirgi versiyaga yangilash yaramaydi. Bilamizki bazi kutubxonalar shu jumladan react o'z type definitionlari bilan kelmaydi. Typelarni alohida
npm i @types/react
orqali o'rnatamiz. Shu joyda etiborga olish kerak bo'lgan narsa bu siz o'rnatayotgan type definitionlar proektdagi typescript versiyasi bilan ishlay olishi kerak. Ko'p type definitionlar DefinitelyTypeddan keladi. DefinitelyTyped o'zlari chiqarayotgan type packagelarni teglar yordamida qaysi typescript versiyalari bilan ishlay olishini ko'rsatib boradi. Manabu misolga qarang.Ko'rib turganingizdek
@types/react
ning versiyalari bilan bir qatorda teglari ham bor. React18 uchun typelarni o'rnatayotganingizda eng ohirgi va sizning typescript versiyangiz bilan ishlay oladigan type definitionlarni o'rnatish kerak. Menda ts4.1 edi shuning uchun @types/react18.0.28
versiyani o'rnatdim18.3.3
yoki18.3.12
ni emas chunki ulardagi ts taglar proektdagi typescript versiyada ancha yuqori.useCallback
hooki. Avvalari unga berilgan callback argumentlarini any deb elon qilgan edi. React18 buni o'zgartiradi va strictroq typing olib kiradi. OldinuseCallback((a, b) => {console.log(a,b)}, [])
qilib yozilsa muammosiz ishlagan kod endi argumentlara, b
implicit any ekanligi haqida xatolik beradi. Men tutgan usul shunchaki hamma useCallback larni ko'rib to'gri typelarni berib chiqish bo'ldi. Codemoddan foydalansangiz ham bo'ladi.React18 da komponent tiplarida
FC, FunctionComponent
endi by defaultchildren
propi mavjud emas. Agar siz shu vaqtgacha bu hususiyatga tayangan bo'lsangiz refactor qilishingiz yoki codemod toollar ishlatishingiz mumkin. Bizni kod baza esa bir o'zim refactor qilib chiqishim uchun kattalik qilardi va bazi biz ishlatayotgan UI liblar hali ham eski React17 typelarda edi. Shuning uchun men reactni FunctionComponent tipini override qilishni maqul ko'rdim. Quyida misol:
// /src/types.d.ts faylidagi koddan parcha
import {PropsWithChildren, ReactElement} from 'react';
declare module 'react' {
interface FunctionComponent<P = {}> {
(props: PropsWithChildren<P>, context?: any): ReactElement<any, any> | null;
}
}
Yangilash davomida
kichik maslahatlar
react-dom
ni yangilagandan keyin albatta yangi APIga o'tishni unutmang. Aynan shu yagona o'zgarish yangi auto batching improvementlarni olib keladi.Yangilash davomida har bir paketni o'rnatgandan keyin proekt development rejimda (localhostda) ishlayotganiga va build (prod uchun) bo'layotganiga ishonch hosil qiling. Nimadir buzilsa joyida hal qilshga yoki keyinroq qaytib kelish uchun yozib borishga harakat qiling. Birdaniga ko'pgina liblarni yangilab keyin projectni run qilsangiz juda ko'p xatolar chiqib adashtirib/motivatsiyani o'ldirib qo'yishi mumkin.
Qachon to'xtashni biling. Reactga aloqador bo'lmagan lekin yangilasa foydali bo'ladigan narsalar bo'lsa unutmaslik uchun alohida backlogga texnik vazifalar qo'shib qo'ying. Bir urunishda iloji boricha kichikroq ko'lamda yangilanishlar qiling. O'zimda bo'lgan holat: reactni yangilayman deb boshlab juda ko'p narsalarni yangilab yubordim, hatto reactga aloqador bo'lmaganlarini ham. Natijada xatolar shunchalik ko'payib ketdiki qaysi errorga focus qilishni bilmay qoldim. Hamma o'zgarishlarni tashlab yuborib qayta boshlashga to'gri keldi. Hatto shundan keyin ham 15ga yaqin dependecylarni almashtirdim, kodni bazi qismlaridan tortib webpack configgacha o'zgartirishlar kiritdim. Lekin birinchi holatdagi urunishdan ancha osonroq bitirdim.
IDE dagi
find and replace
,Project errors
va boshqa featurelardan maksimal foydalaning. Masalan biror bir libda qilingan importlarni o'zgaritish kerak bo'lsa butun boshli proektdagi o'sha libdan qilingan importlarni bittada o'zgaritish imkonini beradigan tayyor toollar bor. Project errors orqali bir vaqtni o'zida proektdagi hamma xatolarni ko'ra olasiz. Bu sizga xatolarni kategoriyalarga ajratib bir vaqtda bir kategoriyaga etibor qaratishga yordam beradi. Kamroq context switch qilasiz bu esa yuqoriroq effektivlik demakdir. Masalan men 100dan ortiq fayllardauseCallback
larni to'grilab chiqish uchun aynan shunday qildim. Vim macrolarga katta rahmat aytib ketmasam ham bo'lmaydi shu joyida ))
Buzilishi mumkin bo'lgan narsalar
React 17dan 18ga o'tishda minimal darajadagi buzilishlarni vada qilgan. Va rostdan ham shunday bo'ldi. Deyarli muammolarga duch kelmadim aynan react ishlashi bo'yicha.
- Hal qilishim kerak bo'lgan yagona muammo bu
useEffect
bilan bo'ldi. Bilamizki useEffetga berilgan callback parametri asinxron bo'lolmaydi chunki u chaqirilganda cleanup funksiya qaytara olishi kerak. Lekin bizdauseMount(callback, deps)
degan custom hook bor ekan. Va u under the hooduseEffect
ni ishlatarkan.useMount
ga berilgan callback asinxron bo'lsa xato kelib chiqadi. Uni to'g'rilash esa 1 qator kodni o'zgartirish bilan bo'ldi.
// useMount.ts fayli:
// eski kod
useEffect(cb, deps);
// yangi kod
useEffect(() => {cb()}, deps);
Buni reactni yangilash muammosi deb bo'lmaydi, shunchaki React18 biz qilayotgan xatoni yaqqol ko'rsatib berdi.
<StrictMode></StrictMode>
Strickt mode development vaqtida dasturdagi muammolarni osonroq topishga yordam beradi lekin productionda hechnimani o'zgartirmaydi. Menda negadir StrictModeda proektda maummolar chiqdi, shunchaki olib tashladim, vohima qilarli joyi yo'q. Keyinchalik vaqt va hohish bo'lganda qo'shib qo'ysa bo'ladi.
Yangilashdan keyin
Proekt development va production rejimda hechqanday muammolarsiz ishlasa yangilashni tugatdim deb hisoblasangiz ham bo'ladi. Lekin bu dasturda hechnarsa buzilmagani haqida kafolat bermaydi. Testlarga tayaning.
Har qanday turdagi testlar unit, e2e yoki integration juda qo'l keladi bunday holatda. Dasturni React17 ishlatayotgan versiyasini va yangilangan versiyasini olib testlarni run qiling va natijalarni solishtiring. Buzilgan narsalar oson va yaqqol ko'rinadi. Bizni dasturni katta qismi autotesterlar tomonidan test qilingan edi. Men shunchaki dasturimizni yangi versiyasini staging enviromentga qo'ydim va autotesterdan testlarini run qilishini so'radim. 2 soatda hal bo'ldi, muammolarsiz.
A/B testing. A/B testingni sozlash infrastruktura tomonlama ozgina qiyinroq lekin aynan bizni holat uchun juda ham foydali bo'ladigan taktika. Foydalanuvchilarning faqatgina bir qismiga (aytaylik 10%) dasturning yangilangan versiyasini ko'rsatib analitik malumotlarni yig'ish orqali o'zimiz uchun hulosa qilish foydali bo'ladi. Lekin bizda A/B testing yo'q va bu uchun DevOps komandani bezovta qilgim kelmadi.
O'qiganingiz uchun rahmat. Post tugadi.
(02.02.2025 Moscow)