Shopee在React?Native?架構方面的探索及發(fā)展歷程
1. 背景
React Native(下文簡稱 RN)是混合應用領域流行的跨端開發(fā)框架。RN 非常適合靈活多變的電商領域業(yè)務,由于 RN 是基于客戶端渲染的技術,所以相較于 H5 頁面,它在用戶體驗方面有一定優(yōu)勢。
伴隨著 Shopee 業(yè)務的飛速發(fā)展,我們 App 中的 RN 代碼量增長得非???,出現(xiàn)了構建產物體積過大、部署時間太長、不同團隊依賴沖突等問題。為了應對這些痛點,我們探索了去中心化的 RN 架構,并結合該模型自研了系統(tǒng)(Code Push Platform,簡稱 CPP)和客戶端 SDK,覆蓋了多團隊的開發(fā)、構建、發(fā)布、運行等一系列 RN 研發(fā)周期。經過近三年的迭代,現(xiàn)已接入多款公司級核心 App。
Shopee 商家服務前端團隊打造了多款商家端應用,大部分用戶是商家服務人員,他們對業(yè)務系統(tǒng)高可用和問題及時反饋有著很高的要求,從而也推動我們對 React Native 的架構有了更高的要求。
本文會從發(fā)展歷史、架構模型、系統(tǒng)設計、遷移方案四個方向逐一介紹我們如何一步步地滿足多團隊在復雜業(yè)務中的開發(fā)需求。
2. 發(fā)展歷程
隨著業(yè)務高速發(fā)展,我們的 RN bundle 個數(shù)飛速增加,App 個數(shù)也達到近十個。整個 RN 項目在開發(fā)模型、部署模型和架構模型三個維度都發(fā)生了變化,從單團隊發(fā)展成多團隊,從一個 bundle 發(fā)展成多個 bundle,從中心化架構發(fā)展成為去中心化,最終發(fā)展成為每個團隊的業(yè)務代碼可以獨立地開發(fā)、部署、運行。
整個發(fā)展歷史分為 4 個階段,分別是單 bundle 集中開發(fā)模式、單 bundle 多業(yè)務組開發(fā)模式、多 bundle 中心化發(fā)布模式、多 bundle 去中心化發(fā)布模式。

2.1 第一階段:單 bundle 集中開發(fā)模式
最初的 RN 整體技術架構相對簡單。由于當時業(yè)務形態(tài)不算復雜,為了滿足獨立團隊在同一個代碼倉庫當中的開發(fā)流程,整個發(fā)布流程是基于 CDN 的更新發(fā)布,并且使用配置文件記錄 RN bundle 文件的版本以及下載地址,以此進行資源管理。整個發(fā)布的產物有兩個,一個是 RN 資源包,一個是用于資源版本管理的 JSON 配置文件。
每次 RN 資源在完成構建后,這兩種構建產物會被放置在靜態(tài)資源目錄下。App 在特定的時間節(jié)點(例如 App 重啟等)會自動拉取配置文件檢查資源更新狀態(tài),然后再從 CDN 拉取 RN 靜態(tài)資源。在下一次打開頁面的時候,App 會加載最新的頁面內容。

隨著業(yè)務發(fā)展,越來越多業(yè)務團隊期望使用 RN 技術棧開發(fā)業(yè)務,這種情況讓已有架構發(fā)生改變,我們自然地產生了“多個業(yè)務組多個代碼倉庫”的想法。
2.2 第二階段:單 bundle 多業(yè)務組開發(fā)模式
針對上述問題,多業(yè)務組的研發(fā)解決方案是 host-plugin 這種模式。
host 用于管理公共依賴和通用邏輯,它將 React、React Native、Shopee RN SDK 等通過一個獨立的倉庫管理起來,保證了特殊 RN 依賴的“singleton”(單例模式)條件,避免了部分客戶端組件的重疊依賴,而這種重疊依賴是 RN 官方不允許的。
一個 host 對應著多個 plugin 倉庫,業(yè)務代碼倉庫則是被看作為一個插件(plugin),以插件的形式接入主應用當中。業(yè)務團隊可以按自己的編碼規(guī)范來管理這個倉庫。每個插件倉庫會被視為 host 項目的 npm 依賴,它的構建是一個集中發(fā)布的流程。所有代碼都會集成在 host 項目當中執(zhí)行構建腳本。這種模式滿足超級 App 的要求。

與此同時,host-plugin 的模式也帶來了一個“難題”,業(yè)務發(fā)展使得 RN 產物體積逐漸變大,過大的產物會影響客戶端的解壓效率和 RN 容器加載 JS 時長。
2.3 第三階段:多 bundle 中心化架構模式
針對 RN 產物體積過大的問題,我們利用構建工具將打包產物細分成多個 bundle,這一優(yōu)化是非常有必要的,我們稱它為“分包”。host 項目對應的是公共包,plugin 項目對應的是業(yè)務包。
整個構建發(fā)生在 host 項目,項目的模式還是“集中構建”和“集中發(fā)布”。多 bundle 產物將會發(fā)布到系統(tǒng)當中,客戶端將拉取熱更新的內容??蛻舳藭葱杓虞d對應的 bundle,RN 容器單次加載消耗的資源大大減少,解決了效率問題。

但是它的缺點也很明顯。隨著業(yè)務團隊的變大和業(yè)務內容的擴張,多 bundle 中心化發(fā)布模式同樣也具備四個弊端:
針對 RN 的運行時,即使分包技術使得產物分離,但是它們還是運行在同一個 JSContext 當中,這種情況可能會導致依賴沖突和環(huán)境變量污染;在開發(fā)調試的過程中,項目重依賴于 host 項目,每次存在著代碼變更,需要重新加載很多內容,讓開發(fā)調試不太友好;在項目構建的過程中,打包速度受到 plugin 個數(shù)的影響,特大型應用甚至需要 50 分鐘執(zhí)行一次構建,過長的構建耗時嚴重影響了發(fā)布效率;在部署發(fā)布的過程中,host 項目維護者負責整個 App,每個業(yè)務組不能獨立發(fā)布,發(fā)布時間會綁定在一起。當出現(xiàn) live issue 的情況,開發(fā)者需要花費大量的溝通成本,且只能整體回滾。 2.4 第四階段:多 bundle 去中心化架構模式
去中心化 React Native 架構模式與網頁的“微前端”或者客戶端的“微應用”的概念類似,滿足了多業(yè)務團隊獨立開發(fā)部署,能夠在同一個 App 各模塊獨立運行。它涵蓋了開發(fā)、構建、發(fā)布、運行等多個方面。該模型解決了上面所說的四個弊端,并針對整個研發(fā)體系有了全面的升級,優(yōu)點有:RN 運行時的互不干擾,開發(fā)調試的高效,構建發(fā)布的獨立性。
下文會重點介紹項目的去中心化 RN 架構和系統(tǒng)設計,以及我們是怎樣做到靈活性和穩(wěn)定性的平衡的。
3. 去中心的 RN 架構模型
簡單來說,去中心化的 RN 發(fā)布模型涉及到四個部分:獨立的 JS 運行時;獨立的開發(fā)流程;獨立的構建流程;獨立的發(fā)布流程。在這四個關鍵環(huán)節(jié)的幫助下,每個團隊按自己的節(jié)奏掌控 RN 的研發(fā)流程。
3.1 獨立 JS 運行時
獨立運行時(多 JSContext,執(zhí)行上下文環(huán)境)的出現(xiàn)是去中心化架構的最大特色。獨立運行時是對獨立發(fā)布的完美保證,將 RN 運行代碼按照 plugin 維度進行隔離,它可以有效避免不同業(yè)務之間的變量沖突以及依賴沖突問題,即“plugin A”的發(fā)布絕對不會影響到“plugin B”。
它的設計主要包含以下三點:
提前創(chuàng)建 JSContext 且預加載公共包;進入 plugin 的頁面,SDK 會查看對應的 JSContext 是否已被實例化。如果已經被實例化,就直接使用,否則從 JSContext Pool 選取一個獨立的上下文,加載執(zhí)行業(yè)務包,各個 plugin 之間運行時是隔離的;退出業(yè)務頁面時,該 JSContext 不會立即銷毀,而是放入一個緩存池,使得重復進入該業(yè)務可以獲得極致體驗。

裝置 JSContext 的容器可以是線程或者進程。為了避免它頻繁創(chuàng)建和回收,我們要維護緩存池且盡可能地復用現(xiàn)有的 JSContext。
這里我們采用 Least Frequently Recently Used(簡稱 LFRU)的策略。當剛退出的應用被重新打開,該 JSContext 會被重新啟用。這樣,我們能夠節(jié)省 85% 的首屏渲染時長。緩存?zhèn)€數(shù)管理是可配置的,業(yè)務方可以根據(jù)應用的規(guī)模作為合理的預估。當該 RN 頁面還在使用中,即使超出預估數(shù),該上下文也不會立即被回收,該設計有效地保證頁面的可用性。

3.2 開發(fā)流程
上文提及 RN 項目的調試效率問題,它會隨著業(yè)務代碼的體量增多,代碼調試效能也會隨之下降。每個開發(fā)者的效率問題直接影響到大家的“幸福感”。相比之下,RN 去中心化發(fā)布則是針對開發(fā)流程做了特定的優(yōu)化。
隨著獨立運行時環(huán)境的出現(xiàn),RN 進入調試的時候,客戶端可以做到只加載一個 plugin 到對應的 JSContext 中,其他 plugin 則采用內置 cache。
這樣做有兩個好處:一是保證了服務啟動范圍的最小化,保證了代碼熱加載的效率;二是確保開發(fā)和構建兩種流程的一致性,這樣會讓一些問題在開發(fā)階段提前暴露出來,比如 babel 插件缺失導致的編譯問題。這樣的“去中心化”的開發(fā)流程提高了 RN 調試效率。

3.3 構建流程
隨著業(yè)務發(fā)展,某 App 的 RN plugin 數(shù)有 4 個,舊構建流程受到 plugin 個數(shù)的影響,集中構建時長超過 20 分鐘。而采用去中心化 RN 架構,構建時長不再隨 plugin 個數(shù)增長,只和該 plugin 代碼量有關,穩(wěn)定在 5 分鐘左右。
新架構也是同樣基于 host-plugin 模型,獨立倉庫的隔離讓每個團隊有自由的發(fā)展空間。考慮到在應用內的基礎 Native 依賴是統(tǒng)一的,host 項目僅用來管理統(tǒng)一的公共依賴。項目需要優(yōu)先將 common bundle 構建完成,系統(tǒng)會記錄公共包中的依賴信息。當每個 plugin 項目進行構建的時候,構建工具會剔除掉公共包依賴信息,并完成業(yè)務包的構建。每個業(yè)務包的構建產物都是獨立地存放于系統(tǒng)當中。系統(tǒng)具備獨立回滾、獨立發(fā)布、獨立灰度的能力。
這樣的好處在于構建任務的最小粒度化,每個 plugin 的構建不會引起整個項目的重新構建,做到真正意義的“按需打包”。

3.4 發(fā)布流程
RN 的構建和發(fā)布是兩個獨立的流程。這也意味著 bundle 的構建環(huán)節(jié)和發(fā)布環(huán)節(jié)完全解耦,發(fā)布時間點也可以由每個業(yè)務團隊發(fā)布負責人靈活安排。每個業(yè)務組對自己的代碼質量負責,靈活地把控自己的發(fā)版本節(jié)奏,不會影響其他團隊線上業(yè)務。發(fā)布流程里面包含了全量發(fā)布、聯(lián)合發(fā)布、灰度發(fā)布、回滾等操作,后續(xù)章節(jié)會詳細介紹如何保證發(fā)布的穩(wěn)定性。
4. 系統(tǒng)設計
對于復雜的大型項目來說,簡單的熱更新流程已無法滿足多業(yè)務組協(xié)同合作,我們需要一個功能完善、性能優(yōu)越、操作友好的熱更新系統(tǒng)來滿足復雜業(yè)務的發(fā)展。Code Push Platform 由 Node.js 編寫,搭配系統(tǒng)附屬的命令行工具和客戶端 SDK。

為了滿足該系統(tǒng)在多業(yè)務團隊的運作,整個系統(tǒng)從功能角度可以劃分為三大部分,分別是:
多團隊權限管控;bundle 生命周期管理;系統(tǒng)效能提升。
其中,系統(tǒng)效能提升功能又細分為:
增量差分;多場景入口體積優(yōu)化;一站式多環(huán)境整合。 4.1 多團隊權限管控
系統(tǒng)除了記錄每次構建操作,更重要的是工作流程的去中心化,每個 plugin 的權限是隔離的。每個負責人只能在系統(tǒng)內部操作,plugin 1 的負責人只能觸發(fā)相關的構建和發(fā)布,沒法看到 plugin 2 的操作情況。系統(tǒng)通過嚴格的權限管控來規(guī)范所有發(fā)布流程,保證了項目的可控性。

React Native 去中心化發(fā)布的設計目標是節(jié)省不同團隊之間的溝通成本。系統(tǒng)會限制他們的構建和發(fā)布的動作,各自的發(fā)布不會互相干擾。
權限的管理呈樹狀結構,一個 App 對應著一個項目,項目負責人默認是 App 團隊的項目負責人。創(chuàng)建一個全新的插件等系統(tǒng)操作需要項目負責人審批。一個 App 包含有多個 plugin,每個 plugin 負責人默認是相應的業(yè)務團隊負責人,他有權限分配發(fā)布和構建的權限。

4.2 bundle 生命周期管理
4.2.1 客戶端版本控制
RN 有別于網頁應用,它對客戶端有著緊密的依賴關系。在客戶端底層依賴沒有變化的情況下,一般情況下開發(fā)者可以通過熱更新進行 RN 代碼的更新。但是遇到重大的更新,例如 React Native 的版本從 59 升級到 63,不僅僅需要 JavaScript 側改動,客戶端也要升級版本且沒法繼續(xù)向下兼容。從技術層面看,它是難以避免的。這種客戶端無法向下兼容的情況,被稱為“斷層”。
系統(tǒng)會提供客戶端版本控制的能力。當重大變更出現(xiàn)時,App 負責人應該在系統(tǒng)上新建一個“斷層信息”,版本號的范圍是從最低 App 兼容版本到最高 App 版本。在這個區(qū)間客戶端才能拉取到該斷層的最新 RN 資源。
如下表所示,大于等于 2.5.0 版本的 App 拉取的是 105 版本 RN 包;在 2.0.0 至 2.5.0 版本拉取到 103 版本 RN 包;在 1.0.0 至 2.0.0 版本拉取到 100 版本 RN 包。

這種措施能夠有效避免潛在風險。而最新的需求只會在最新斷層上線,舊的斷層只做線上問題修復。畢竟是兩套代碼,代碼的維護有成本,隨著用戶更新至最新版本,應當逐漸淘汰掉舊斷層。
4.2.2 灰度和回滾
發(fā)布流程里面包含了全量發(fā)布、灰度發(fā)布、回滾等操作。對于大型需求,全量上線會帶來潛在風險。一般來說,優(yōu)先針對部分用戶投放新版本,發(fā)布負責人可以根據(jù)指定用戶和特定范圍進行灰度發(fā)布,逐步擴大灰度發(fā)布范圍,直至轉到全量。當發(fā)現(xiàn)重大 bug 的時候,發(fā)布者可以采用“零構建”的方式進行“秒級”回滾。
去中心化 RN 架構支持每個 plugin 獨立發(fā)布、獨立灰度、獨立回滾,以最小顆粒度的操作來保證質量規(guī)避風險。plugin 維度級別的灰度和回滾能夠為不同的業(yè)務團隊帶了靈活性,每個業(yè)務團隊可以自行發(fā)布版本,控制灰度節(jié)奏,處理線上問題。
4.3 系統(tǒng)效能提升
4.3.1 差分增量
App 頻繁更新 RN 資源包會造成對用戶流量的消耗,最有效的方式是利用增量更新來節(jié)省流量。RN 資源包涵蓋了編譯后的 JavaScript 產物、圖片、翻譯文件等靜態(tài)資源。它們的前后版本差異即是該版本變更的代碼或者其他資源文件。為了讓差分粒度深入到資源包內部,系統(tǒng)專門提供獨立的“差分服務”,采用二進制差分的方式對構建產物進行差分。
RN 資源包的 diff(差分)操作在服務端完成 ,patch(整合)操作在 App 端完成。在去中心化 RN 架構中,每個 plugin 的差分都是獨立的。plugin 的發(fā)布會自動觸發(fā)差分的執(zhí)行,系統(tǒng)會以 plugin 為維度拉取最近五個版本,Diff Server 則會依次將它們和當前版本進行差分計算。如果計算成功,會將差分結果上傳到 CDN 并反饋給系統(tǒng),否則繼續(xù)重試。整個差分操作是一個異步的過程,即使出現(xiàn)“差分服務”下線等極端情況,系統(tǒng)會自動降級為全量包,保證系統(tǒng)的可用性。

4.3.2 多場景入口體積優(yōu)化
由于 React Native 的構建官方依賴于 metro.js,而它并沒有具備無用代碼剔除(tree-shaking)的能力。隨著業(yè)務代碼的膨脹,包體積的優(yōu)化是一個很重要的問題。
例如,ShopeePay 為公司多款核心 App 提供支付業(yè)務。ShopeePay plugin 在不同地區(qū)、不同 App 之間存在一些頁面級別差異。同一個倉庫含了所有代碼和資源,但是構建腳本會將它們都會打包成為一個產物。很明顯,這導致 ShopeePay 的發(fā)布產物包含大量冗余資源,并非最優(yōu),浪費下載流量,同時也影響代碼的執(zhí)行效率。
我們采用自研的多場景插件(babel-plugin-scene),該插件通過注入的環(huán)境變量設置一個場景值,babel 可以根據(jù)場景值的差異化加載不同的文件,并且以默認文件作為降級兜底。不同場景對應不同的入口文件,利用這種形式可以有效控制包體積。

4.3.3 一站式多環(huán)境融合
一個正常的研發(fā)流程是從 test 環(huán)境,到 uat 環(huán)境,再到 live環(huán)境。Code Push Platform 對接了 App 的 test/uat/live環(huán)境,所以 RN 開發(fā)者只需要在該系統(tǒng)就可以進行“一站式”的操作,方可滿足一個需求的整個研發(fā)周期。
不同環(huán)境的包資源流轉,是多環(huán)境融合的一大亮點。如果某 RN bundle 在 uat 環(huán)境構建,它也不需要重新構建,將 bundle 無縫轉換到 線上 環(huán)境進行發(fā)布。它帶來的優(yōu)勢在于“零構建時長”以及資源包的穩(wěn)定性,因為 bundle 沒有重新進行構建,所以它的內容已經在 uat 得到了充分的驗證,發(fā)布風險更小。

5. 舊業(yè)務的遷移方案
如何遷移現(xiàn)有業(yè)務的 App 是一個非常嚴肅的問題,特別是歷史背景較重的業(yè)務,它們可能存在“邏輯耦合”或者“組件耦合”的場景。與此同時,很多相關業(yè)務都在需求迭代當中,系統(tǒng)的遷移是不能阻礙需求迭代,所以舊業(yè)務“漸進式遷移”方案是非常必要的。
5.1 邏輯耦合
如果兩個以上 plugin 存在邏輯依賴關系,用戶必須同時加載到最新的 plugin??紤]到熱更新失敗的可能性,邏輯耦合就是多個 plugin 隱藏著一種約束關系。例如,訂單業(yè)務和購買業(yè)務存在一定的邏輯耦合關系,發(fā)布負責人針對流量極大的超級 App,不可能逐個發(fā)布 plugin。在極端的狀態(tài)下,用戶可能會先加載到 plugin A,新版本的 plugin A 和舊版本的 plugin B 是不兼容的,這樣會帶來嚴重后果。遇到這種情況,有兩種解決方案:
方案一:plugin 間邏輯解耦,保證每個 plugin 的獨立性。
方案二:系統(tǒng)提供了聯(lián)合發(fā)布,在 Native 側保證多個 plugin 能夠同時加載到最新。
方案一是最理想化的狀態(tài),但是在業(yè)務場景細分的情況下,項目結構很難做到絕對獨立。
針對老業(yè)務可以考慮方案二,系統(tǒng)提供了 module 的概念,一個 module 對應著兩個以上的 plugin。它們存在著一個綁定的關系。在同一個下載任務里面,客戶端 SDK 以“事務”形式,保證多個 plugin 能夠同時下載完成并投入使用。聯(lián)合發(fā)布這個能力在系統(tǒng)層面,有效規(guī)避這種錯誤的可能性。

5.2 組件耦合
如果說聯(lián)合發(fā)布是針對在 plugin 維度的“邏輯耦合”兼容方案,“組件耦合”則是更細粒度的組件級別的耦合關系。也就是說,一個頁面中存在多個組件來自不同的團隊,例如商品詳情頁等頁面有評價功能組件。這種“一個頁面存在著 JSContext 相互嵌套”的情景存在于電商業(yè)務當中。
針對這種“組件耦合”情況,有兩種解決方案:
方案一:嵌套組件抽離成為一個獨立倉庫,供第三方 plugin 使用。
方案二:使用“同屏渲染”的能力實現(xiàn)“多 Context 嵌套”。
方案一是最理想的解決方案。但是考慮到遷移成本,我們也提供了方案二(一種“同屏渲染”嵌套組件)來支持這種場景,它類似一種 Native 組件。在多個 JSContext 的情況下,通過 plugin 名和頁面名將所需要的內容嵌套到另一個頁面當中。
如下圖所示,plugin A 會嵌套 plugin B 的內容,A 和 B 也可以實現(xiàn)在同一個屏幕進行渲染。從 Web 的方向理解,這種情況有點像 “iframe” 的場景,支持多個頁面的嵌套。它非常易于 RN 開發(fā)者的理解,客戶端 SDK 能夠動態(tài)加載目標 bundle 并將它渲染在合適的位置。

5.3 漸進式遷移
對于現(xiàn)有的 App,因為業(yè)務沒法暫停迭代,我們難以一次性完成整體遷移。因此,我們提供了“漸進式遷移”方案。考慮到歷史背景,該方案不會一次性把所有 plugin 都遷移,而是逐步拆分,再遷移接入到新發(fā)布系統(tǒng)。
遷移的步驟如下圖所示:
優(yōu)先將獨立的業(yè)務遷移到 Code Push Platform,它們享用一個獨立的 JSContext;所有“待拆分代碼”共用一個獨立的JSContext;將“待拆分代碼”繼續(xù)拆分成幾個獨立 plugin,獨立使用 JSContext,其他內容則保持步驟二的狀態(tài)。
隨著版本迭代,重復第二和第三步驟,直至歷史業(yè)務全部拆分完畢。這樣我們可以達到一個最優(yōu)的目標,即是真正意義的“獨立構建”和“獨立發(fā)布”。

6. 總結
該系統(tǒng)的目標在于滿足所有 App 的多團隊研發(fā)協(xié)作效率問題,去中心化 RN 發(fā)布模型考慮到“獨立運行時”、“獨立開發(fā)”、“獨立構建”、“獨立發(fā)布”四大方面,保障了每個 plugin 運行的獨立性。最終目標在于支撐 Shopee 的多個 RN 團隊在不同 App 平臺根據(jù)自己節(jié)奏自由發(fā)布且高效運作。
系統(tǒng)設計涉及到“多團隊權限管控”、“客戶端版本控制”、“灰度和回滾”、“增量差分”、“多入口包體積優(yōu)化”、 “一站式多環(huán)境融合”,加速了整個研發(fā)流程,真正做到了“靈活性”和“穩(wěn)定性”的兼得。
到此這篇關于Shopee在React Native 架構方面的探索的文章就介紹到這了,更多相關React Native 架構內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
react中hooks使用useState的更新不觸發(fā)dom更新問題及解決
這篇文章主要介紹了react中hooks使用useState的更新不觸發(fā)dom更新問題及解決,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01
React Native基礎入門之初步使用Flexbox布局
React中引入了flexbox概念,flexbox是屬于web前端領域CSS的一種布局方案,下面這篇文章主要給大家介紹了關于React Native基礎入門之初步使用Flexbox布局的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下2018-07-07
react項目升級報錯,babel報錯,.babelrc配置兼容等問題及解決
這篇文章主要介紹了react項目升級報錯,babel報錯,.babelrc配置兼容等問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08
基于React-Dropzone開發(fā)上傳組件功能(實例演示)
這篇文章主要介紹了基于React-Dropzone開發(fā)上傳組件,主要講述的是在React-Flask框架上開發(fā)上傳組件的技巧,需要的朋友可以參考下2021-08-08
React中useEffect原理的代碼簡單實現(xiàn)詳解
React的useEffect鉤子是React函數(shù)組件中處理副作用,本文將通過一個簡單的例子解釋如何用代碼實現(xiàn)useEffect的基本原理,感興趣的小伙伴可以了解下2023-12-12

