前言
從2023年6月22日React Native官方發(fā)布0.72.0至今,一年多的時(shí)間React Native官方已經(jīng)陸續(xù)發(fā)布了0.73汁政、0.74道偷、0.75三個(gè)版本,故決定對(duì)公司項(xiàng)目做版本升級(jí)烂完,以獲得更好的性能和穩(wěn)定性试疙。
我們先看下這三個(gè)版本诵棵,帶來了哪些新功能抠蚣、新特性:
React Native 0.73
新的調(diào)試器:增加了新的調(diào)試器,棄用舊版flipper調(diào)試工具履澳,讓調(diào)試過程更加高效順暢嘶窄。
穩(wěn)定的符號(hào)鏈接支持: 簡(jiǎn)化您的開發(fā)工作流程怀跛,輕松將文件或目錄鏈接到其他位置。
支持 Android 14: 確保您的應(yīng)用適配最新系統(tǒng)柄冲,兼容更多用戶設(shè)備吻谋。
全新實(shí)驗(yàn)性功能:無橋模式 (Bridgeless Mode),直接將 JavaScript 代碼編譯為原生代碼现横,顯著提升應(yīng)用性能并降低內(nèi)存使用量漓拾。
Android 平臺(tái)默認(rèn)使用 Kotlin。
React Native 0.74
Yoga 3.0:引入了 Yoga 3.0戒祠,增強(qiáng)了布局引擎的性能骇两。
Yarn 3:初始化新React Native項(xiàng)目時(shí),使用Yarn 3作為默認(rèn)JavaScript包管理器姜盈,取代了之前的經(jīng)典版Yarn(1.x)低千。
新架構(gòu)下的默認(rèn)無橋接模式:在啟用新架構(gòu)時(shí),默認(rèn)采用無橋接模式(Bridgeless)馏颂,以提高性能和效率示血。
新架構(gòu)批量onLayout更新:在0.74版本中,onLayout回調(diào)中的狀態(tài)更新被批處理救拉,這意味著連續(xù)的狀態(tài)更新將合并成一次渲染提交难审,從而減少不必要的重新渲染。
最低 SDK 要求提高:安卓的最低 SDK 版本要求從 Android 5.0(API 21)提高到 Android 6.0(API 23)近上,這有助于減小應(yīng)用在用戶設(shè)備上占用的空間剔宪,例如新創(chuàng)建的應(yīng)用體積減少了約13%,節(jié)約了約4MB的空間壹无。
棄用 PropTypes:完全移除了 React Native 內(nèi)置的 PropTypes葱绒,推薦使用 TypeScript 進(jìn)行類型檢查。
移除廢棄API:刪除了PropTypes等已棄用API斗锭,推薦開發(fā)者遷移至TypeScript
React Native 0.75
Yoga 3.1和布局改進(jìn):支持%值在布局中的應(yīng)用地淀,如gap、translation等屬性岖是,但僅適用于新架構(gòu)帮毁。
新架構(gòu)穩(wěn)定化:修復(fù)了一些Bug,提高了穩(wěn)定性豺撑,并在React Native Directory中添加了新架構(gòu)支持信息烈疚,還發(fā)布了關(guān)于支持新架構(gòu)中UIManager的文章。
使用框架:推薦通過框架(如Expo)構(gòu)建React Native應(yīng)用聪轿,將/template文件夾移至單獨(dú)的倉(cāng)庫(kù)爷肝,并計(jì)劃在2024年12月31日停止使用react-native init命令,同時(shí)改進(jìn)了自動(dòng)鏈接的性能。
Touchable在TypeScript中的使用限制:TouchableOpacity和TouchableHighlights組件不能再用作類型灯抛,應(yīng)使用React.ElementRef或View類型金赦。
其他變更:包括Android和iOS中一些API的刪除、重命名以及功能的遷移等对嚼。
由于一個(gè)完整的 React Native 項(xiàng)目是由 Android 項(xiàng)目夹抗、iOS 項(xiàng)目和 JavaScript 項(xiàng)目組成的,且都打包在一個(gè) npm 包中纵竖,所以升級(jí)可能會(huì)有一些麻煩漠烧,大體上就是如下兩種升級(jí)思路。
一靡砌,在老項(xiàng)目基礎(chǔ)上升級(jí)
如果你選擇通過在老項(xiàng)目基礎(chǔ)上改變package.json中package版本號(hào)重新yarn的方式升級(jí)沽甥,建議你使用React Native官方推薦的升級(jí)助手:Upgrade React Native applications,通過填寫app信息乏奥,會(huì)給出詳細(xì)的升級(jí)方案摆舟,你只需要按照提示逐行更改就行。
由于Upgrade Helper給出的改動(dòng)方案篇幅過長(zhǎng)邓了,這里就不全部給出了恨诱。大致上重點(diǎn)在于,由于0.73默認(rèn)使用kotlin骗炉、廢棄了flipper且新增了新的調(diào)試器照宝,需要將iOS podfile和安卓項(xiàng)目配置中關(guān)于flipper的部分全部刪除,并且將.java文件刪除替換為相應(yīng)kotlin代碼的.kt文件句葵,還有一些安卓SDK厕鹃、Gradle及npm包的升級(jí),只需要按照提示改就行了乍丈,主要工作量都在iOS剂碴、Android原生項(xiàng)目配置這兩塊,JavaScript 項(xiàng)目只占很小一部分工作量轻专。這個(gè)過程可能并不會(huì)一次成功忆矛,參考Upgrading to new versions · React Native和Upgrade Helper給出的方案,遇到什么問題解決什么問題就好了请垛。
二催训,新建項(xiàng)目升級(jí)
以我以往的升級(jí)經(jīng)驗(yàn)來看,在老項(xiàng)目的基礎(chǔ)上通過改變package.json中package版本號(hào)重新yarn的方式升級(jí)宗收,結(jié)合Upgrade Helper給出的改動(dòng)方案漫拭,iOS、Android原生項(xiàng)目配置需要改動(dòng)的東西很多混稽,且很容易出現(xiàn)其他未知錯(cuò)誤采驻,通過這種方式升級(jí)儿捧,弄不好要花費(fèi)掉一個(gè)星期的時(shí)間。
所以我選擇直接 init 一個(gè)新的項(xiàng)目挑宠,然后把現(xiàn)有項(xiàng)目的 JS 代碼拷貝過來,iOS颓影、Android原生項(xiàng)目配置重新配置一遍的方式手動(dòng)升級(jí)各淀。這樣我將在一個(gè)干凈的React Native 0.75 空項(xiàng)目的基礎(chǔ)上添磚加瓦,因?yàn)樾枰诳枕?xiàng)目上將原來的iOS诡挂、Android原生部分重新配置一遍碎浇,看似更麻煩了,實(shí)則可以規(guī)避掉了很多在老項(xiàng)目基礎(chǔ)上升級(jí)帶來的未知錯(cuò)誤璃俗,直至代碼拷貝完成奴璃、升級(jí)成功。
值得一提的是城豁,為了確保npm package的版本與React Native 0.75保持同步苟穆,我并沒有直接將老項(xiàng)目package.json的內(nèi)容直接拷貝到新項(xiàng)目的package.json中yarn,而是將每一個(gè)npm package都yarn add一遍唱星,自動(dòng)去安裝最新的版本雳旅。
yarn完成后,安卓項(xiàng)目需要Android Studio重新sync Android Gradle和gradlew --refresh-dependencies刷新依賴间聊,iOS項(xiàng)目需要重新pod install攒盈,這些都是必不可少的。
運(yùn)行pod install后哎榴,報(bào)錯(cuò):
Build target hermes-engine: Command PhaseScriptExecution failed with a nonzero exit code
此時(shí)需要將/Users/xxx/Library/Developer/Xcode/DerivedData/yourapp/Logs/Build/中的.log文件轉(zhuǎn)換成可被閱讀的.xcactivitylog文件才能查看到具體的報(bào)錯(cuò)型豁,cd到上訴文件夾,運(yùn)行如下命令:
for LOG in *.xcactivitylog; do
NAME=`basename $LOG $EXT`
gunzip -c -S $EXT "${NAME}${EXT}" > "${NAME}.log"
done
在xcactivitylog中得到具體的報(bào)錯(cuò)信息如下:
Build target hermes-engine of project Pods with configuration Release
warning: Run script build phase '[CP-User] [Hermes] Replace Hermes for the right configuration, if needed' will be run during every build because it does not specify any outputs. To address this warning, either add output dependencies to the script phase, or configure it to run in every build by unchecking "Based on dependency analysis" in the script phase. (in target 'hermes-engine' from project 'Pods')
Run script build phase '[CP-User] [Hermes] Replace Hermes for the right configuration, if needed' will be run during every build because it does not specify any outputs. To address this warning, either add output dependencies to the script phase, or configure it to run in every build by unchecking "Based on dependency analysis" in the script phase.
PhaseScriptExecution [CP-User]\ [Hermes]\ Replace\ Hermes\ for\ the\ right\ configuration,\ if\ needed /Library/Developer/Xcode/DerivedData/myProjectName-gzdlehmipieiindfjyfrhhcjupam/Build/Intermediates.noindex/ArchiveIntermediates/myProjectName/IntermediateBuildFilesPath/Pods.build/Release-iphoneos/hermes-engine.build/Script-46EB2E0002C950.sh (in target 'hermes-engine' from project 'Pods')
Node found at: /var/folders/d5/f1gffcfx27ngwvmw8v8jdm7m0000gn/T/yarn--1704767526546-0.12516067745295967/node
/Library/Developer/Xcode/DerivedData/myProjectName-gzdlehmipieiindfjyfrhhcjupam/Build/Intermediates.noindex/ArchiveIntermediates/myProjectName/IntermediateBuildFilesPath/Pods.build/Release-iphoneos/hermes-engine.build/Script-46EB2E0002C950.sh: line 9: /var/folders/d5/f1gffcfx27ngwvmw8v8jdm7m0000gn/T/yarn--1704767526546-0.12516067745295967/node: No such file or directory
Command PhaseScriptExecution failed with a nonzero exit code
通過查找方案https://github.com/facebook/react-native/issues/42221尚蝌,采用軟鏈接node到/usr/local/bin/node的方式解決了該問題迎变,具體步驟如下:
1,找到真實(shí)的node路徑
command -v node # in my machine that show => /Users/runner/hostedtoolcache/node/18.20.2/arm64/bin/node
2飘言,鏈接node到 /usr/local/bin/node.
ln -s /Users/runner/hostedtoolcache/node/18.20.2/arm64/bin/node /usr/local/bin/node
或者
ln -s $(command -v node) /usr/local/bin/node
還遇到了xcode報(bào)錯(cuò):
Build service could not create build operation: unknown error while handling message: MsgHandlingError(message: "unable to initiate PIF transfer session (operation in progress?)")
通過重啟xcode解決氏豌。
期間也遇到一些npm package相關(guān)的報(bào)錯(cuò),由于每個(gè)項(xiàng)目使用的npm package都不一樣热凹,未必能為其他人帶來幫助泵喘,這里就不過多論述。
至此般妙,React Native從0.72到0.75的版本升級(jí)就完成了纪铺,總耗時(shí)一天時(shí)間。