使用React進行組件庫開發

最近針對平常業務需求使用react封裝了一套[組件庫], 大概記錄下整個開發過程當中的心得。因爲篇幅緣由,在這裏只對開發過程當中比較糾結的選型和打包等進行討論,後續再對具體組件的封裝進行討論。
文章首發於 我的博客

概述

咱們都知道,組件化的開發模式對於咱們的開發效率有着極大的提高,針對咱們平常使用的基本組件進行封裝,能夠大量的簡化咱們對於基本UI的關注度,讓咱們的工做聚焦在業務邏輯上,很好的分離業務與基礎UI的代碼,使得整個項目更有調理,這也是咱們要進行本組件庫開發的緣由。css

然而現有React開源組件有不少,像ant-design和material-ui等等,是否須要花費精力打造適合自身團隊的組件庫每每須要酌情考慮。咱們來看下我現有團隊及業務的幾個特色:前端

  1. 前端人員較多,須要相互協做,且有餘力對組件進行開發
  2. 產品業務相對複雜,需對某些組件進行定製化開發
  3. 已經有成熟的設計規範,針對各類基礎組件、基礎樣式等進行定義
  4. 目前的項目較爲凌亂,第三方組件引用雜亂無章

能夠看出,咱們擁有封裝本身組件的精力和基礎,而且擁有經過基礎組件封裝改變目前開發現狀的需求。因此,這件事情是咱們應該而且須要儘快完成的事情。node

技術選型

針對組件庫的封裝,咱們首先面對的是技術選型以及方案的規劃。大概包括如下兩點:react

  • 最基本的技術方案
  • 開發流程和規範

技術方案選擇

Webpack + React + Sasswebpack

因爲團隊現有的項目都是基於React+Redux進行開發的,那咱們選擇的開發語言無疑是React。git

SASS

針對css選擇,雖然如今針對組件化開發,比較流行CSS Modules
和CSS-IN-JS兩中模塊化解決方案,咱們更但願咱們的組件是可進行定製的。所以針對組件,咱們以Sass做爲預編譯語言,提搞效率和規範性。配合css-modules,咱們能夠很方便的進行鍼對實際需求進行樣式更改。例如咱們有一個Tab組件,咱們已經定義好了其通用的樣式:github

.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爲其添加惟一的模塊樣式:web

<Tab styleName="unique-tab" />

針對該模塊,對其進行基本樣式的修改:npm

.unique-tab {
  :global {
      .tip-tab-item {
        border-color: #eee;
        
        &.active {
          border-color: blue;
        }
      }
  }
}

這樣,針對該模塊的定製樣式,能很好的進行鍼對需求的樣式定製,同時不對全局樣式進行污染。json

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這種優秀的組件庫,能學到不少的東西。更深入的理解封裝組件的思想,是一個很好的過程。

相關文章
相關標籤/搜索