React構建簡潔強大可擴展的前端項目架構
引言
React
技術棧的一大優(yōu)勢在于 —— 社區(qū)繁榮,你業(yè)務中需要實現(xiàn)的功能基本都能找到對應的開源庫。
但繁榮也有不好的一面 —— 要實現(xiàn)同樣的功能,有太多選擇,到底選哪個?
本文要介紹一個12.7k的開源項目 —— Bulletproof React
這個項目為構建簡潔、強大、可擴展的前端項目架構的方方面面給出了建議。
Bulletproof React是什么
Bulletproof React
與我們常見的腳手架(比如CRA
)不同,后者的作用是根據模版創(chuàng)建一個新項目。
而前者包含一個完整的React
全棧論壇項目:
作者通過這個項目舉例,展示了與項目架構相關的13個方面的內容,比如:
- 文件目錄該如何組織
- 工程化配置有什么推薦
- 寫業(yè)務組件時該怎么規(guī)范
- 怎么做狀態(tài)管理
API
層如何設計- 等等......
限于篇幅有限,本文介紹其中部分觀點。
不知道這些觀點你是否認同呢?
文件目錄如何組織
項目推薦如下目錄形式:
src | +-- assets # 靜態(tài)資源 | +-- components # 公共組件 | +-- config # 全局配置 | +-- features # 特性 | +-- hooks # 公用hooks | +-- lib # 二次導出的第三方庫 | +-- providers # 應用中所有providers | +-- routes # 路由配置 | +-- stores # 全局狀態(tài)stores | +-- test # 測試工具、mock服務器 | +-- types # 全局類型文件 | +-- utils # 通用工具函數
其中,features
目錄與components
目錄的區(qū)別在于:
components
存放全局公用的組件,而features
存放業(yè)務相關特性。
比如我要開發(fā)評論模塊,評論作為一個特性,與他相關的所有內容都存在于features/comments
目錄下。
評論模塊中需要輸入框,輸入框這個通用組件來自于components
目錄。
所有特性相關的內容都會收斂到features
目錄下,具體包括:
src/features/xxx-feature | +-- api # 與特性相關的請求 | +-- assets # 與特性相關的靜態(tài)資源 | +-- components # 與特性相關的組件 | +-- hooks # 與特性相關的hooks | +-- routes # 與特性相關的路由 | +-- stores # 與特性相關的狀態(tài)stores | +-- types # 與特性相關的類型申明 | +-- utils # 與特性相關的工具函數 | +-- index.ts # 入口
特性導出的所有內容只能通過統(tǒng)一的入口調用,比如:
import { CommentBar } from "@/features/comments"
而不是:
import { CommentBar } from "@/features/comments/components/CommentBar
這可以通過配置ESLint
實現(xiàn):
{ rules: { 'no-restricted-imports': [ 'error', { patterns: ['@/features/*/*'], }, ], // ...其他配置 } }
相比于將特性相關的內容都以扁平的形式存放在全局目錄下(比如將特性的hooks存放在全局hooks目錄),以features
目錄作為相關代碼的集合能夠有效防止項目體積增大后代碼組織混亂的情況。
怎么做狀態(tài)管理
項目中并不是所有狀態(tài)都需要保存在中心化的store中,需要根據狀態(tài)類型區(qū)別對待。
組件狀態(tài)
對于組件的局部狀態(tài),如果只有組件自身以及他的子孫組件需要這部分狀態(tài),那么可以用useState
或useReducer
保存他們。
應用狀態(tài)
與應用交互相關的狀態(tài),比如打開彈窗、通知、改變黑夜模式等,應該遵循將狀態(tài)盡可能靠近使用他的組件的原則,不要什么狀態(tài)都定義為全局狀態(tài)。
以Bulletproof React
中的示例項目舉例,首先定義通知相關的狀態(tài):
// bulletproof-react/src/stores/notifications.ts export const useNotificationStore = create<NotificationsStore>((set) => ({ notifications: [], addNotification: (notification) => set((state) => ({ notifications: [...state.notifications, { id: nanoid(), ...notification }], })), dismissNotification: (id) => set((state) => ({ notifications: state.notifications.filter((notification) => notification.id !== id), })), }));
再在任何使用通知相關的狀態(tài)的地方引用useNotificationStore
,比如:
// bulletproof-react/src/components/Notifications/Notifications.tsx import { useNotificationStore } from '@/stores/notifications'; import { Notification } from './Notification'; export const Notifications = () => { const { notifications, dismissNotification } = useNotificationStore(); return ( <div > {notifications.map((notification) => ( <Notification key={notification.id} notification={notification} onDismiss={dismissNotification} /> ))} </div> ); };
這里使用的狀態(tài)管理工具是zustand
,除此之外還有很多可選方案:
context
+ hooks
redux
+ redux toolkit
mobx
constate
jotai
recoil
xstate
這些方案各有特點,但他們都是為了處理應用狀態(tài)。
服務端緩存狀態(tài)
對于從服務端請求而來,緩存在前端的數據,雖然可以用上述處理應用狀態(tài)的工具解決,但服務端緩存狀態(tài)相比于應用狀態(tài),還涉及到緩存失效、序列化數據等問題。
所以最好用專門的工具處理,比如:
react-query - REST
+ GraphQL
swr - REST
+ GraphQL
apollo client
- GraphQL
urql
- GraphQl
表單狀態(tài)
表單數據需要區(qū)分受控與非受控,表單本身還有很多邏輯需要處理(比如表單校驗),所以也推薦用專門的庫處理這部分狀態(tài),比如:
React Hook Form
Formik
React Final Form
URL狀態(tài)
URL
狀態(tài)包括:
url params
(/app/${dynamicParam})
query params
(/app?dynamicParam=1)
這部分狀態(tài)通常是路由庫處理,比如react-router-dom
。
總結
本文節(jié)選了部分Bulletproof React
中推薦的方案,有沒有讓你認可的觀點呢?
以上就是React構建簡潔強大可擴展的前端項目架構的詳細內容,更多關于React前端項目架構的資料請關注腳本之家其它相關文章!
相關文章
React組件創(chuàng)建與事件綁定的實現(xiàn)方法
react事件綁定時。this并不會指向當前DOM元素。往往使用bind來改變this指向,今天通過本文給大家介紹React事件綁定的方式,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧2022-12-12React Native中NavigatorIOS組件的簡單使用詳解
這篇文章主要介紹了React Native中NavigatorIOS組件的簡單使用詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-01-01