如何實現React元件的可複用性
可複用性一詞是當今軟體工程領域上最為常見的流行詞之一。可複用性早已成為大量不同框架、工具乃至模型都需要承諾的一種特性,且每一個所實現的方式與對該特性的詮釋都各不相同。
那麼,可複用性到底指的是什麼?
真正的可複用性指的並非是一種特定的流程,而是一個開發策略。因而,在構建可複用元件時,開發者必須得把可複用性牢記在腦海裡。因為,這將涉及到無比細緻的規劃及善解人意的 API 設計。再者,既然可複用性早已被現代的開發工具與框架所支援且倡導,那麼我們就不能僅僅通過單一的技術手段去實現該特性 —— 而需要開發團隊之間的一致實現過程以及一個機構(Organizations)所有層面上的技術約定。
因此,當我們談及可複用性時,這並不僅僅只是一場技術性的討論。相反,它往往還會綜合有公司的文化、培訓以及其他很多的要素。其中部分的要素還會在本文中所觸及,可關鍵點在於可複用性是一個會觸及到方方面面的過程,包括開發的各個階段與一個機構中的各個層面。
由於沃爾瑪(Walmart)公司旗下包含有若干個品牌,其中包括山姆俱樂部(Sam’s Club)、阿斯達(Asda)以及一些地區分支,如沃爾瑪(加拿大)與沃爾瑪(巴西)等,因此,大量的前端應用會穿插在不同的品牌之間執行且由上百名開發者進行構建與維護。
也正是因為每一個品牌都會擁有著屬於自己的線上品牌容貌,且開發者往往需要在一個所有沃爾瑪品牌都共通的元件上工作 —— 例如,圖片輪播(Image Carousel)、像麵包屑(Bread Crumbs)的導航式元素、彈框和信用卡 Form 元件等。因而,往往就會存在有重複工作的現象。可眾所周知的是,重複地去完成別人已完成的事情只是在浪費時間與金錢,且會增加問題所出現的機率。因此,只要能消除這樣的重複性工作,開發者就能把更多的時間花費在使用者體驗的提升上面。
當然,也許你會說對於後端來說,在不同的品牌間共享程式碼會使得事情變得更為直觀:即一個單一的伺服器能處理來自不同品牌的多個請求,並返回對應品牌的精確資料(基於資料形式的處理方法並非只有一個)。可你是否曾想到,對於前端來說,這樣的情況就會變得更為複雜。因為這將涉及到對後端所提供的資料進行提取,並把主題及其他資訊準確地應用到一個特定的品牌和檢視上。所以,共享程式碼儘管能促進元件的複用,但這並不能完全地去解決問題。
@沃爾瑪實驗室(@WalmartLabs)對 React 元件的複用
關於網站 Walmart.com 的構建,React 是我們當初所選擇的前端框架。至於為何作出這樣的抉擇,其中一個原因在於其元件模型能為程式碼的複用提供一個好的起始點,尤其是當我們需要結合 Redux 來管理 State。儘管如此,Walmart 的體量對前端程式碼的複用仍然會帶有顯著的挑戰。
共享程式碼的技術可能性
共享程式碼所涉及的首個技術挑戰是 —— 元件需要能被版本化,且易於安裝及升級。對此,我們會把所有的 React 元件放置在一個分離的 GitHub 機構(Organizations)中。可目前,儘管元件已被打包放入至建立團隊的倉庫中,但我們仍然需要把部分的元件移至按功能分類的倉庫,如“導航欄”倉庫會包含有面包屑、標籤及側導航連結元件。然後,元件就會被髮布至我們的私有 npm 倉庫。這也就意味著開發者能非常容易地安裝一個具有特定版本的元件,並保證其程式不會因版本的升級而突然拋錨。
至此,既然程式碼能在團隊間進行共享,那麼,不管元件的依賴是否更新或替換,我們都需要保證其結構與程式碼的一致性。這也就是為什麼我們要為元件與應用創造出 Electrode 原型。該原型不僅包含有用於程式碼規範、轉譯及封裝的配置檔案,而且還提供有用於管理核心程式碼依賴與任務/指令碼的核心。這樣一來,從一個通用的結構開始,建立起專案間一致的程式碼標準就能使得機構能維持有最好的現代化實踐,且能同時增強開發者間的程式設計信心,與提高可複用元件所真正被複用的機會。此外,一個包含有程式碼規範、效能估算與多裝置、多平臺及多解析度測試的穩定持續整合/持續部署(Continuous Integration/Continuous Deployment)系統同樣會起到進一步的促進效果。詳細來說,持續整合系統會在 PR 請求提交時包含有所有的規則,併釋出一個 beta 測試版本,以供所有相關程式測試。這樣的話,就能保證此次 PR 不會影響到任何的地方。
元隊(The Meta Team)
在專案初期,由於大部分的共享元件是由少量的團隊所貢獻完成的,因而它們更新迭代的速度會變得越來越快。從而最終導致我們不得不選擇少部分對 Electrode 原型與沃爾瑪內部具有深入瞭解的開發者,來創造出我們所稱作的“元隊”。而被選中的人會在數週內抽出若干小時乃至一整天的時間去對機構中正在執行的元件程式碼進行審查,以確保開發者能遵循實踐,並儘可能地協助他們去解決問題。此外,該團隊還會就機構中所構建的東西總結出一整套知識體系,並充當著使者的角色去為自己團隊中採用 Electrode 原型的專案提供服務。而且,元隊成員還會把關於原型修改待決的部分資訊帶至自己的團隊中,以收集回饋並與 Electrode 原型的核心開發團隊進行分享和探討。
儘管,好的開始是成功的一半。但作為一個機構,我們仍然能看到程式碼複用更進一步的提升空間。
上百個元件的暴露性問題
隨著共享主題的策略實施,我們開始注意到 Slack 頻道上所湧現出來的大量資訊。開發者希望能有一種方式去得知是否已經有現有的元件能完成一個特定的任務,UX 團隊希望能檢視到哪些元件是可用的,而專案經理則希望能檢視到哪些元件是其他團隊正在構建中的。也就是說,所有這些資訊所圍繞的共同焦點就在於元件是否能被暴露。針對於此,我們迫切需要一種快速且簡單的方法,去發現可用的元件並檢視它們的使用情況。從而能與這些元件進行互動,以瞭解它們的實現、配置及依賴。
那麼,問題答案就在於我過去曾寫文討論的一樣東西 —— Electrode 勘探器。開發者通過該勘探器不僅能瀏覽到@沃爾瑪實驗室中上百個可用的元件及其文件,而且還能瀏覽到元件的版本提交記錄,以檢視其各階段的程式碼修改情況。正是因為 Electrode 勘探器能提供機構中所有元件的 Web 介面,因而開發者此時已不再需要鍵入 npm install
來檢視並使用元件。
縫隙間所溢位的重複元件
儘管,所有的這些工具與工作流程都是在促進程式碼的複用,但問題依舊存在。而其中一點就是,開發團隊在開發新元件時往往會忽略掉元件對其他團隊所起到的作用。倘若元件沒有被涵蓋在可複用的生態系統當中,那麼,這就意味著該元件無法被其他人複用。即便是存在於同一套共享元件系統,大量重複或一些對相似問題採用不同解決辦法的元件依舊存在。因而,我們這才意識到技術手段並非能完全地解決問題。所以,此時此刻我們需要的是一種辦法。它不僅能廣泛地改變公司人員的思考方式,而且還能使得所有層面的工作人員都能事事以可複用性當先。這也就包括了花費時間去對之前的元件進行歸納總結,以便複用變得更為簡單;在已有元件的基礎上進行擴充套件,而不是從零開始;不斷地去尋找機會來儘可能地與外界共享程式碼。
為了協助思想上的這種改變,我們建立了一套元件開發的提案流程。在此係統下,開發者需要在工作開始前先討論關於新元件的一切事宜,以便機構中的其他團隊能根據此事來推薦出已有的解決方案或可選方法。這樣,機構中的其他人也就能知道發生著怎樣的事情。
實踐證明,在開發過程當中採用該種提案系統能有效地幫助我們解決縫隙間所溢位的重複元件問題。
持續整合/持續部署系統的重要性
過去,我們曾遇到過這樣的一個重大的問題:一個團隊在元件上的開發可能會導致其他團隊的程式拋錨。換而言之,如果你不對元件的版本進行鎖定,持續整合/持續部署系統可能會因為元件被其他團隊所修改,而導致出錯 —— 這是一個非常糟糕的感覺。甚者還會到導致大量團隊需要封鎖自身元件至一個特定的版本,而無法使用新的補丁版本。
這也就是為何我們需要引入一個穩定的持續整合/持續部署系統。當一個元件版本更新時,不管其他重要的程式是否對該元件的版本進行鎖定,系統中的自動裝置都會去檢查本次更新是否會導致程式主版本的崩潰。若無,則生成一個 PR 請求去更新鎖定的版本至最新版本號;而若有,則通知涉事團隊雙方去檢討問題的所在。
內部資源
關於提高 React 元件可複用性的這些方法都是基於 Laurent Desegur 早前寫文所描述的關於開放資源/內部資源哲學思想的一些領會。隨著像 Hapi、OneOps 與 Electrode 等一些專案的展現,可以看到@沃爾瑪實驗室在過去幾年已逐漸成為開源征途上的使用者及貢獻者。儘管,在公司外面的人看來,我們對內部資源看似甚少貢獻,即那些基於開源模型所開發的內部程式。但是,對於內部資源來說,並沒有任何一個團隊或成員會真正地“擁有”一個元件。換句話說,所有的元件是共享在整個機構當中的,而這也就意味著能消除開發的瓶頸並驅使開發者去提升已有元件的質量。
採用這樣的策略不僅能很好地提高元件複用的機率,而且更為重要的是,還能為我們的開發者及開發協作的哲學思想提供有一定指引。而且,策略一定程度上能驅使開發者把自己的時間和專業知識使用在最需要的地方,而不是靜待技術瓶頸的消除。這樣的話,他們就能以真實且可量化的方式讓公司受益。
總結
可複用性不僅是一種技術性的決策,而且還是一種需要機構性保障,且具有深遠意義的哲學思想。通過@沃爾瑪實驗室這個例子,我們就可以清晰地看到其所產生的效益是何等巨大。如今,開發者們也正在把 SamsClub.com 移植到 Electrode 平臺上,並複用數百個來自 Walmart.com 的元件去匹配山姆俱樂部的品牌容貌。
當然,最後你也可以跟我們分享一下自己關於可複用性的一些故事,包括當中遇到了哪些阻礙?怎麼去解決?以及你所能看到的哪些更深層次的提升?
相關文章
- React元件複用的方式React元件
- 如何編寫一個可複用元件元件
- 可複用的快取元件快取元件
- 元件複用那些事兒 - React 實現按需載入輪子元件React
- React、Redux與複雜業務元件的複用ReactRedux元件
- REACT元件抽象與複用React元件抽象
- 實現基於React的全域性提示元件ToastReact元件AST
- 簡述用React實現Table元件React元件
- react篇章-React 元件-複合元件React元件
- React 實現一個簡單實用的 Form 元件ReactORM元件
- React元件化複用的一些技巧React元件化
- 基於RabbitMQ.Client元件實現RabbitMQ可複用的 ConnectionPool(連線池)MQclient元件
- 面向可複用性和可維護性的設計模式設計模式
- 可複用 React 的 HOC 以及的 Render PropsReact
- 用react-redux實現react元件之間資料共享ReactRedux元件
- react複合元件的使用React元件
- react 元件的屬性React元件
- React中元件邏輯複用的那些事兒React元件
- Web Components 系列(十一)—— 實現 MyCard 的可複用Web
- 「實戰」純React實現的拖拽元件React元件
- React實現元件全屏化React元件
- React Hook 提高程式碼複用性ReactHook
- React.Component 損害了複用性?React
- 可複用程式碼:元件的來龍去脈元件
- 第5章:可複用性的軟體構建方法 5.1可複用性的度量,形態和外部觀察
- React 元件屬性React元件
- Vue.js可複用性 & 組合Vue.js
- React - Context API 維護全域性狀態,實現全域性元件通訊ReactContextAPI元件
- React Hooks 實現的中文輸入元件ReactHook元件
- 【React原始碼解讀】- 元件的實現React原始碼元件
- react實現一個button元件React元件
- iOS動態性可複用而且高度解耦的使用者統計埋點實現iOS解耦
- 如何基於 Channel 實現多路複用
- 如何實現一流的專案可預測性?
- 自定義元素探祕及構建可複用元件最佳實踐元件
- 基於CMS的元件複用實踐元件
- 基於React版本16.2.0的原始碼解析(一):元件實現(小白也可讀)React原始碼元件
- React Native 實現 Slider 元件React NativeIDE元件