<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>

          如何創(chuàng)建可擴展和可維護的前端架構

          共 5183字,需瀏覽 11分鐘

           ·

          2021-12-09 17:23

          大廠技術  高級前端  Node進階

          點擊上方 程序員成長指北,關注公眾號

          回復1,加入高級Node交流群

          現代的前端框架和庫可以輕松地創(chuàng)建可重用的 UI 組件。在創(chuàng)建可維護前端應用方面,這是一個很好的方向。但是,在多年來的許多項目中,我發(fā)現開發(fā)可重復使用的組件常常是不夠的。我的項目由于需求的變化或者新需求的出現而變得不可維護。要查找正確的文件或調試多個文件所需的時間越來越長。

          必須改變。我可以提高搜索技能,或者更熟練地使用 Visual Studio Code。但我并不是唯一在前端工作的人。所以,我們需要對前端項目進行設置。要讓它們變得更易于維護和擴展。那意味著我們可以對當前特性進行修改,但也可以更快地添加新特性。

          1高級架構

          對于后端開發(fā),我們可以遵循很多架構模式。領域驅動開發(fā)(domain-driven development,DDD)和關注點分離(separation of concerns,SoC)是目前使用的兩個概念。這兩個概念給前端開發(fā)帶來了巨大價值。在 DDD 中,你試著把相似的特性分組合起來,并盡量使它們和其他組(比如模塊)解耦。而在 SoC 中,例如,我們可以分離邏輯、試圖和數據模型(例如,使用 MVC 或 MVVM 設計模式)。

          希望現代的前端應用程序能完成越來越多的繁重工作。當復雜度增加時,Bug 也會變得更加頻繁。由于用戶和前端的交互,我們需要一個既可維護又可擴展的可靠架構。在這一點上,我的首選架構是模塊化和領域驅動的。記住,我的想法也許會改變,但這是我此刻首選的方式。

          當用戶與我們的應用交互時,應用將路由引導用戶到正確的模塊。每一個模塊都被完全包含。然而,如果用戶想要使用一個應用,而非幾個小應用,就會有一些藕合。該耦合存在于特定的特性或業(yè)務邏輯中。有幾個特性可以在模塊間共享。你可以將該邏輯放在應用層。也就是說,每個模塊可以選擇與應用層進行交互。例如,需要通過客戶端的 API 連接到后端,或者設置 API 網關。

          在查看項目的結構時,我們可以遵循如下所示的內容。應用層的所有代碼都在 app 目錄下。并且所有的模塊都有一個目錄,位于 modules 目錄下。不依賴業(yè)務邏輯的可重復使用的 UI 組件(如表格)在 components 目錄下。

          app/assets/components/lib/modules/styles/

          其余的目錄存放我們的靜態(tài) assets(如圖片)或者 lib 中的輔助函數。輔助函數可以非常簡單。它們可以將某些東西轉換為某種格式,或者幫助處理對象。但更復雜的代碼可以存放于 lib 目錄中。處理模式或圖的工作(例如檢查有向圖中的循環(huán)的算法)也不例外。

          很多人都使用 CSS-in-JS 或樣式組件之類的東西,但是我更喜歡普通的 CSS。為什么呢?無需 JavaScript,我們可以使用 CSS 和 HTML 解決很多 UI 問題。當我們應用 SoC 的概念時,這會變得更加容易。此外,在一個地方維護 CSS 使你更容易維護,因為你可以減少重復的工作。它要求一個穩(wěn)定的 CSS 架構。盡管我會在另一篇博文中討論這個問題,但是我的 CSS 架構是基于 Harry Roberts 的 ITCSS。

          2填寫應用細節(jié)

          通過高層和項目結構,我們已經有了一個良好的開端。然而,為了實現這一前端架構,我們還需要更多的細節(jié)。我們先來看看更詳細的架構圖,如下圖所示。在這幅圖中,我放大了應用層,但同時也放大了一個模塊。在我們的前端應用中,應用層是我們的核心,所以我們首先討論它。

          應用層由兩部分組成:存儲和客戶端 API。存儲是我們的全局應用狀態(tài)。這個狀態(tài)保存著不同模塊在同一時間可以存取的數據。即使在屏幕上不需要這些數據,它也會持續(xù)存在于存儲中。正如你所看到的,每一個發(fā)送到存儲的更新請求都可以通過一連串的邏輯。這就是我們所說的中間件。這是 Redux 中使用的一種模式。中間件的一個簡單例子是記錄存儲的傳入請求。

          有時候,需要通過外部服務中的數據對存儲的傳入請求進行增強。在 Redux 中,我們使用 Promise 處理這個調用。它可能是后端服務,但是它也可能是公共的第三方 API。有些情況下,只需使用瀏覽器 fetch API 就可以實現單一目的的 REST 調用。如果希望使用同一個 API 來執(zhí)行不同的調用,那么創(chuàng)建 API 客戶端定義是個不錯的想法。

          基本的 API 客戶端處理外部請求、響應和錯誤。你甚至可以讓它為你提供有關請求狀態(tài)的信息(例如,加載)。不過,更復雜的 API 客戶端可以處理更多的事情。有些 API 通過 web-socket 連接甚至是 GraphQL API。在這種情況下,你將擁有更多的配置選項,如下圖所示。

          對于更加復雜的 API 客戶端,我們可以通過中間件修改所有發(fā)出的請求(例如,添加認證頭)。響應可以由后件修改(比如更改數據結構)。更改響應之后,我們將其存儲在客戶端的緩存中,這就像應用存儲一樣。有什么不同嗎?緩存只處理傳入的 API 數據,而我們可以把任何數據放入應用存儲里。

          很多前端應用都會有專門的后端服務來對話。無論是在有許多微服務的 Kubernetes 集群之上的 API 網關,還是一個單一的單體后端。但是有時候我們需要連接到不同的外部服務。使用這種架構,我們可以創(chuàng)建大量的 API 客戶端。每個 API 客戶端都有緩存、中間件和后件。我們應用的不同部分應該能夠與這些 API 客戶端中的每一個進行交互。

          應用目錄的相應項目結構可以如下所示:

          app/  api/config/  store/pubsub/  schemas/  index.js

          app 中的兩個目錄現在聽起來應該很熟悉:api 和 store。這兩個目錄保存了與前面描述的用例有關的所有內容。config 存放靜態(tài)定義和配置(比如常量),用于整個應用。schemas 描述了 JavaScript 對象的特定數據結構。這在使用 TypeScript 或 JavaScript 時都可以使用。應用的所有通用模式都存儲在 schemas 目錄中。

          pubsub 是一個很好的例子,它可以擴展前端的基本架構。pubsub 可以用于模塊通信或管理預定作業(yè)。因為它對于應用的核心很重要,所以它位于 app 目錄內。最后,我們得到了 index.js 文件。通過這個文件,我們可以添加 app 目錄中的所有函數和常量。這就是說,這個文件的功能是進入應用邏輯的入口點。

          3模塊的架構

          介紹了應用層之后,就剩下模塊了。詳細的架構圖已經顯示了一個模塊的內部結構。如果應用的路由指向一個特定的模塊時,這個模塊就會決定路由應該如何繼續(xù)。模塊的路由決定哪個頁面應該顯示。一個頁面包括許多 UI 組件,也就是用戶在屏幕上看到的內容。

          在本例中,頁面與 UI 組件沒有任何區(qū)別。它是一個大的 UI 組件。然而,其他模塊可以與組件(和動作)交互,但不能與頁面交互。只有使用嵌套路由才能使來自不同模塊的頁面相互作用。這就是說,你將模塊的路由放在不同模塊的頁面中。

          組件通過動作與應用層交互。這些動作可能表現為各種形式。它們可以是普通的 JavaScript 函數、Redux 相關函數或者 React Hooks。有時候,你有一些小的實用函數專門用于某些模塊。如果是這樣,你可以將它們放到 actions 目錄下,也可以為模塊創(chuàng)建一個專門的 utils 目錄。下面顯示了項目的模塊結構:

          users/  actions/  components/config/    constants.js    routes.js    tables.js        forms.js  pages/gql/  schemas/  index.js

          和應用層一樣,我們也可以有靜態(tài)代碼(如常量或模式定義),而只涉及到我們的模塊。本例中,我們將這些代碼放入 config 或 schema 目錄下。在使用 GraphQL 時,可以有查詢和變異的定義。這些應該放在 gql 目錄下(或者一個具有相似用途的目錄)。添加 interface.js 文件,用于存儲該模塊的應用。這個文件描述了如何訪問存儲中的數據。

          index.js 作為 app 目錄的 index.js。在這里,我們描述了供他人訪問的所有的組件、動作和常量。

          4模塊的通信

          并不是每個模塊都需要擁有上述所有的目錄和文件。比如,有些模塊不需要頁面,因為它們只包括組件和動作。“files”模塊就是一個很好的例子。這個模塊結合了組建和動作來查看和上傳文件。一個例子是一個拖放文件的區(qū)域,將結果上傳到一個 blob 存儲。它可以成為可重復使用的組件。但是,文件的實際上傳取決于我們能夠使用的服務。我們通過將 UI 組件和上傳文件的實際動作結合起來,創(chuàng)建了一個小的包含模塊。將組件與業(yè)務邏輯結合在一起時,我們將其轉換為模塊。

          但是其他模塊是如何使用文件模塊中的組件或者動作的?模塊的 index.js 文件描述了哪些組件、動作和常量可以被其他組件訪問。因此,我們可以在文件模塊中使用文件拖放區(qū)或上傳動作。然而,有時候我們需要選擇我們想要公開的內容。這是一個動作,還是我們要將這一動作合并為一個組件?

          下面來看看用戶下拉列表的示例。通過創(chuàng)建動作,可以為我們提供可以從不同模塊選擇的所有用戶。不過,現在我們需要在其他所有模塊中創(chuàng)建一個特定的下拉列表。這可能不需要太多努力,就能得到一個通用的下拉組件。但這個組件可能無法在窗體中工作。也許有必要創(chuàng)建一個可以使用的 UserDropdown 組件。現在我們只在用戶周圍更改一個組件時更改。因此有時候我們需要選擇公開的內容:動作或組件。

          在組件之間使用的一種高級模式是使用 pubsub。在這個模式下,不能共享組件,但是我們可以共享數據。上面的圖片說明了它的工作原理。再一次強調一下,這是一種高級模式,僅當你想要走微型前端路線或者需要的時候。

          5UI 組件剖析

          還缺少最后一個細節(jié)層面,那就是 UI 組件的架構。我在以前的博文中已經對此進行過描述。你可以從這種解剖圖中看到一些我們已經廣泛應用的概念。

          前端是用戶的第一個入口點。當前端項目特性增加時,我們也引入了更多的 Bug。但是我們的用戶期望沒有 Bug,新特性也會更快。那不可能。但是,只要有了一個好的架構,我們就能盡可能達到這個目標。

          作者介紹:

          Kevin Pennekamp,富有創(chuàng)意的前端工程師。喜歡 CSS,并遵循一些基本的工程原則。

          原文鏈接:

          作者 | Kevin Pennekamp
          譯者 | Sambodhi
          策劃 | 辛曉亮
          來自|InfoQ
          https://dev.to/crinklesio/how-to-create-a-scalable-and-maintainable-front-end-architecture-4f47
          Node 社群


          我組建了一個氛圍特別好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你對Node.js學習感興趣的話(后續(xù)有計劃也可以),我們可以一起進行Node.js相關的交流、學習、共建。下方加 考拉 好友回復「Node」即可。


             “分享、點贊在看” 支持一波??

          瀏覽 55
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <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>
                  色情网站免费观看在线观看 | 老鸭窝毛片 | 丁香五月激情六月 | 男女啪啪啪啪网站 | 欧美精品三级视频在线看 |