<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          社區(qū)精選 | 一個(gè)簡(jiǎn)潔、強(qiáng)大、可擴(kuò)展的前端項(xiàng)目架構(gòu)是什么樣的?

          共 6433字,需瀏覽 13分鐘

           ·

          2022-07-27 03:46

          今天為各位帶來(lái)的是社區(qū)作者 卡頌 的文章,在這篇文章他介紹了一個(gè)開(kāi)源項(xiàng)目,這個(gè)項(xiàng)目為構(gòu)建簡(jiǎn)潔、強(qiáng)大、可擴(kuò)展的前端項(xiàng)目架構(gòu)的方方面面給出了建議。一起來(lái)看看吧~



          大家好,我卡頌。


          React技術(shù)棧的一大優(yōu)勢(shì)在于 —— 社區(qū)繁榮,你業(yè)務(wù)中需要實(shí)現(xiàn)的功能基本都能找到對(duì)應(yīng)的開(kāi)源庫(kù)。


          但繁榮也有不好的一面 —— 要實(shí)現(xiàn)同樣的功能,有太多選擇,到底選哪個(gè)?


          本文要介紹一個(gè)12.7k的開(kāi)源項(xiàng)目 —— Bulletproof React

          https://github.com/alan2207/bulletproof-react


          這個(gè)項(xiàng)目為構(gòu)建簡(jiǎn)潔、強(qiáng)大、可擴(kuò)展的前端項(xiàng)目架構(gòu)的方方面面給出了建議。


          Bulletproof React是什么



          Bulletproof React與我們常見(jiàn)的腳手架(比如CRA)不同,后者的作用是根據(jù)模版創(chuàng)建一個(gè)新項(xiàng)目。


          而前者包含一個(gè)完整的React全棧論壇項(xiàng)目:



          作者通過(guò)這個(gè)項(xiàng)目舉例,展示了與項(xiàng)目架構(gòu)相關(guān)的13個(gè)方面的內(nèi)容,比如:


          • 文件目錄該如何組織

          • 工程化配置有什么推薦

          • 寫(xiě)業(yè)務(wù)組件時(shí)該怎么規(guī)范

          • 怎么做狀態(tài)管理

          • API層如何設(shè)計(jì)

          • 等等......


          限于篇幅有限,本文介紹其中部分觀點(diǎn)。


          不知道這些觀點(diǎn)你是否認(rèn)同呢?


          文件目錄如何組織



          項(xiàng)目推薦如下目錄形式:


          src
          |
          +-- assets            # 靜態(tài)資源
          |
          +-- components        # 公共組件
          |
          +-- config            # 全局配置
          |
          +-- features          # 特性
          |
          +-- hooks             # 公用hooks
          |
          +-- lib               # 二次導(dǎo)出的第三方庫(kù)
          |
          +-- providers         # 應(yīng)用中所有providers
          |
          +-- routes            # 路由配置
          |
          +-- stores            # 全局狀態(tài)stores
          |
          +-- test              # 測(cè)試工具、mock服務(wù)器
          |
          +-- types             # 全局類(lèi)型文件
          |
          +-- utils             # 通用工具函數(shù)


          其中,features目錄與components目錄的區(qū)別在于:


          components存放全局公用的組件,而features存放業(yè)務(wù)相關(guān)特性


          比如我要開(kāi)發(fā)評(píng)論模塊,評(píng)論作為一個(gè)特性,與他相關(guān)的所有內(nèi)容都存在于features/comments目錄下。


          評(píng)論模塊中需要輸入框,輸入框這個(gè)通用組件來(lái)自于components目錄。


          所有特性相關(guān)的內(nèi)容都會(huì)收斂到features目錄下,具體包括:


          src/features/xxx-feature
          |
          +-- api         # 與特性相關(guān)的請(qǐng)求
          |
          +-- assets      # 與特性相關(guān)的靜態(tài)資源
          |
          +-- components  # 與特性相關(guān)的組件
          |
          +-- hooks       # 與特性相關(guān)的hooks
          |
          +-- routes      # 與特性相關(guān)的路由
          |
          +-- stores      # 與特性相關(guān)的狀態(tài)stores
          |
          +-- types       # 與特性相關(guān)的類(lèi)型申明
          |
          +-- utils       # 與特性相關(guān)的工具函數(shù)
          |
          +-- index.ts    # 入口


          特性導(dǎo)出的所有內(nèi)容只能通過(guò)統(tǒng)一的入口調(diào)用,比如:


          import { CommentBar } from "@/features/comments"


          而不是:


          import { CommentBar } from "@/features/comments/components/CommentBar


          這可以通過(guò)配置ESLint實(shí)現(xiàn):

          {
            rules: {
              'no-restricted-imports': [
                'error',
                {
                  patterns: ['@/features/*/*'],
                },
              ],
              // ...其他配置
            }
          }


          相比于將特性相關(guān)的內(nèi)容都以扁平的形式存放在全局目錄下(比如將特性的hooks存放在全局hooks目錄),以features目錄作為相關(guān)代碼的集合能夠有效防止項(xiàng)目體積增大后代碼組織混亂的情況。


          怎么做狀態(tài)管理



          項(xiàng)目中并不是所有狀態(tài)都需要保存在中心化的store中,需要根據(jù)狀態(tài)類(lèi)型區(qū)別對(duì)待。


          組件狀態(tài)


          對(duì)于組件的局部狀態(tài),如果只有組件自身以及他的子孫組件需要這部分狀態(tài),那么可以用useStateuseReducer保存他們。


          應(yīng)用狀態(tài)


          與應(yīng)用交互相關(guān)的狀態(tài),比如打開(kāi)彈窗、通知、改變黑夜模式等,應(yīng)該遵循將狀態(tài)盡可能靠近使用他的組件的原則,不要什么狀態(tài)都定義為全局狀態(tài)


          Bulletproof React中的示例項(xiàng)目舉例,首先定義通知相關(guān)的狀態(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),
              })),
          }));


          再在任何使用通知相關(guān)的狀態(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


          這些方案各有特點(diǎn),但他們都是為了處理應(yīng)用狀態(tài)


          服務(wù)端緩存狀態(tài)


          對(duì)于從服務(wù)端請(qǐng)求而來(lái),緩存在前端的數(shù)據(jù),雖然可以用上述處理應(yīng)用狀態(tài)的工具解決,但服務(wù)端緩存狀態(tài)相比于應(yīng)用狀態(tài),還涉及到緩存失效、序列化數(shù)據(jù)等問(wèn)題。


          所以最好用專門(mén)的工具處理,比如:


          • react-query - REST + GraphQL

          • swr - REST + GraphQL

          • apollo client - GraphQL

          • urql - GraphQl


          表單狀態(tài)


          表單數(shù)據(jù)需要區(qū)分受控與非受控,表單本身還有很多邏輯需要處理(比如表單校驗(yàn)),所以也推薦用專門(mén)的庫(kù)處理這部分狀態(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)通常是路由庫(kù)處理,比如react-router-dom


          總結(jié)



          本文節(jié)選了部分Bulletproof React中推薦的方案,有沒(méi)有讓你認(rèn)可的觀點(diǎn)呢?

          歡迎在評(píng)論區(qū)交流項(xiàng)目架構(gòu)中的最佳實(shí)踐。



          SegmentFault 思否社區(qū)小編說(shuō)


          自 2022-07-01 起 SegmentFault 思否公眾號(hào)改版啦!之后將陸續(xù)推出新的欄目和大家見(jiàn)面!(請(qǐng)拭目以待呀~?


          在「社區(qū)精選」欄目中,我們將為廣大開(kāi)發(fā)者推薦來(lái)自 SegmentFault 思否開(kāi)發(fā)者社區(qū)的優(yōu)質(zhì)技術(shù)文章,這些文章全部出自社區(qū)中充滿智慧的技術(shù)創(chuàng)作者哦!


          希望通過(guò)這一欄目,大家可以共同學(xué)習(xí)技術(shù)干貨,GET 新技能和各種花式技術(shù)小 Tips。


          歡迎越來(lái)越多的開(kāi)發(fā)者加入創(chuàng)作者的行列,我們將持續(xù)甄選出社區(qū)中優(yōu)質(zhì)的內(nèi)容推介給更多人,讓閃閃發(fā)光的技術(shù)創(chuàng)作者們走到聚光燈下,被更多人認(rèn)識(shí)。


          「社區(qū)精選」投稿郵箱:[email protected]

          投稿請(qǐng)附上社區(qū)文章地址




          點(diǎn)擊左下角閱讀原文,到 SegmentFault 思否社區(qū) 和文章作者展開(kāi)更多互動(dòng)和交流,公眾號(hào)后臺(tái)回復(fù)“ 入群 ”即可加入我們的技術(shù)交流群,收獲更多的技術(shù)文章~

          - END -


          瀏覽 59
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  日韩成人在线电影 | 人人看人人做 | 国产综合久久777777麻豆 | 日韩Aⅴ高清 | www.黄色电影 |