詳解使用React進行組件庫開發,詳解react組件庫
最近針對日常業務需求使用react封裝了一套[組件庫], 大概記錄下整個開發過程中的心得。由於篇幅原因,在這裡只對開發過程中比較糾結的選型和打包等進行討論,後續再對具體組件的封裝進行討論。
概述
我們都知道,組件化的開發模式對於我們的開發效率有著極大的提升,針對我們日常使用的基本組件進行封裝,可以大量的簡化我們對於基本UI的關注度,讓我們的工作聚焦在商務邏輯上,很好的分離業務與基礎UI的代碼,使得整個項目更有調理,這也是我們要進行本組件庫開發的原因。
然而現有React開源組件有很多,像ant-design和material-ui等等,是否需要花費精力打造適合自身團隊的組件庫往往需要酌情考慮。我們來看下我現有團隊及業務的幾個特點:
- 前端人員較多,需要相互協作,且有餘力對組件進行開發
- 產品業務相對複雜,需對某些組件進行定製化開發
- 已經有成熟的設計規範,針對各種基礎組件、基礎樣式等進行定義
- 目前的項目較為淩亂,第三方組件引用雜亂無章
可以看出,我們擁有封裝自己組件的精力和基礎,並且擁有通過基礎組件封裝改變目前開發現狀的需求。所以,這件事情是我們應該並且需要儘快完成的事情。
技術選型
針對組件庫的封裝,我們首先面對的是技術選型以及方案的規劃。大概包括以下兩點:
- 最基本的技術方案
- 開發流程和規範
技術方案選擇
Webpack + React + Sass
由於團隊現有的項目都是基於React+Redux進行開發的,那我們選擇的開發語言無疑是React。
SASS
針對css選擇,雖然現在針對組件化開發,比較流行CSS Modules和CSS-IN-JS兩中模組化解決方案,我們更希望我們的組件是可進行定製的。因此針對組件,我們以Sass作為先行編譯語言,提搞效率和規範性。配合css-modules,我們可以很方便的進行針對實際需求進行樣式更改。例如我們有一個Tab組件,我們已經定義好了其通用的樣式:
.tip-tab { border: 1px solid #ccc;}.tip-tab-item { border: 1px solid #ccc; &.active { border-color: red; }}
而在業務中,針對某一個需求,我們需要針對Tab組件的樣式進行微調。讓其在啟用(active)狀態下border-color是藍色的。你當然可以說,我們可以讓我們的組件暴露出一些props,針對這些修改進行配置,傳入不同的props對應不同的風格。但是我們往往無法滿足所有的業務需求,不可能針對組件把各種樣式都封裝進去。針對這種方案,我們採用css-modules為其添加唯一的模組樣式:
<Tab styleName="unique-tab" />
針對該模組,對其進行基本樣式的修改:
.unique-tab { :global { .tip-tab-item { border-color: #eee; &.active { border-color: blue; } } }}
這樣,針對該模組的定製樣式,能很好的進行針對需求的樣式定製,同時不對全域樣式進行汙染。
Icon
針對項目表徵圖,計劃使用svg-sprite方案。但是由於產品處於在不斷迭代的過程中,新的表徵圖不斷在增加。目前我們並不會對表徵圖統一進行打包,而是在每次進行組件打包的過程中,從項目中匯入所有的表徵圖。用以下方式進行引入:
import Icon from '@common/lib'import errorIcon from '@images/error.svg'<Icon link={errorIcon} />
其實更好的方式是針對所有的表徵圖進行統一打包,產生svg-spirte檔案(具體原理可以查詢svg-sprite,在此不再贅述)。當我們進行使用時,只需直接引用即可,避免每次都進行打包,減少webpack處理依賴的時間:
<Icon type="error" />
開發流程和規範
針對開發流程和規範,我們遵循以下幾個原則:
- 組件庫完全獨立於項目進行開發,便於後續多重專案進行使用等
- 組件庫包含三種模式:開發,測試,打包,文檔案例,區分不同的入口及狀態
- 使用pure-renderautobind等儘可能保證組件的效能及效率
- 保證props和回調的語義性,如回調統一使用handleXXX進行處理
為了便於後續的擴充,我們更希望整個組件庫完全脫離於項目進行開發。保證組件庫僅對於最基本的組件進行封裝,將項目UI代碼與商務邏輯進行分離。
針對不同的模式下,我們有不同的檔案入口,針對開發模式,我們啟動一個dev-server, 在裡面對組件進行基本的封裝,並進行調試。打包時,我們只需對組件內容進行封裝,暴露統一的介面。在文檔中,我們需要進行案例和說明的展示。所以我們在利用webpack的特性進行各種環境的配置:
npm run dev // 開發npm run test // 測試npm run build // 構建npm run styleguide // 文檔開發npm run styleguide:build // 文檔打包
組件庫作為項目的最小力度支援,我們需要保證其最基本的渲染效率,因此我們採用pure-render/autobind等對其進行基本的最佳化。React有很多最佳化方式,在此不進行贅述。
打包
基礎
針對組件庫的打包,我們以UMD格式對其進行打包。webpack可以針對輸出進行格式設定:(引自cnode)
- “var” 以變數方式輸出
- “this” 以 this 的一個屬性輸出: this[“Library”] = xxx;
- “commonjs” 以 exports 的一個屬性輸出:exports[“Library”] = xxx;
- “commonjs2” 以 module.exports 形式輸出:module.exports = xxx;
- “amd” 以 AMD 格式輸出;
- “umd” 同時以 AMD、CommonJS2 和全域屬性形式輸出。
配置如下:
output: { path: config.build.assetsRoot, filename: utils.assetsPath('js/[name].js'), chunkFilename: utils.assetsPath('js/[id].js'), library: 'TipUi', libraryTarget: 'umd'}
依賴
很明顯,我們封裝的是一個針對React的組件庫,並不應該把React引用進去。一般我們可以採用externals的方式對其進行處理。
在這裡, 我們採用dll方式將其與其他第三方依賴統一進行打包,並將manifest.json和三方依賴的輸出檔案輸出到項目中去,在項目中也使用dllReference進行引用。避免在項目中使用到這些依賴時重複進行打包。
同時,由於我們的組件庫處於一個不斷維護的狀態。這就需要我們維持好項目庫和項目之間的打包關係,具體的流程:
在每次進行項目打包的時候,首先檢測UI庫是否有更新,若沒有更新,則直接進行打包。反之繼續檢測dll的依賴是否有變化,若有,則打包dll,否則直接打包組件庫內容。然後將輸出結果同步到項目中,再進行最終打包。
當然,以上的這些流程都是自動進行的。
文檔和樣本
一個完善的文檔對於一個組件庫是及其重要的,每個組件有什麼樣的配置參數,擁有哪些事件回調,對應的Demo和展示效果。假設沒有這些,除了封裝組件的人,沒有人知道它該如何使用。但是寫文檔的過程往往是痛苦的,在這裡推薦幾個文檔產生庫,可以極大的簡化文檔工作:
docsify 基於Vue的組件產生器,輕量好用
react-styleguidist 基於React的組件庫文檔產生器,自動根據注釋產生文檔,支援Demo展示。超好用
bisheng ant design自己寫的文檔產生器
我們使用的styleguidist, 可以將md自動轉化為文檔,支援在md內直接調用你封裝好的組件並進行展示,簡單好用。最後封裝的文檔大概長這樣:
總結
其實封裝組件庫這種工作有很多的東西值得琢磨和鑽研,由於篇幅原因,在這裡只對開發過程中比較糾結的選型和打包等進行討論,後續再對具體組件的封裝進行討論。在書寫的同時,不斷參考下ant design這種優秀的組件庫,能學到很多的東西。更深刻的理解鎖裝組件的思想,是一個很好的過程。
以上就是本文的全部內容,希望對大家的學習有所協助,也希望大家多多支援幫客之家。