漫談 React 組件庫開發(二):組件庫最佳實踐

在 React 大生態下,一個比較成熟的前端團隊,都會面對一個問題:如何提升團隊的開發效率?css

一個系統擁有大量的業務場景和業務代碼,類似的頁面和代碼層出不窮,如何管理和抽象這些類似的代碼和模塊,這確定是諸多團隊都會遇到的問題。 不斷的拷代碼?仍是抽象成 UI 組件或業務組件?顯而後者更高效。前端

那麼如今就面臨一個選擇:一是選擇 React 生態中已有的組件庫,例如 antDesign、Material-UI 等比較成熟的組件庫;二是團隊再開發一套屬於本身的組件庫。有贊前端團隊選擇了後者,產出並開源了 Zent ,Zent 提供了一整套基礎的 UI 組件以及經常使用的業務組件,目前咱們有 45+ 組件,這些組件都已經在有讚的各種 PC 業務中普遍使用。本文咱們就來聊一聊如何開發一套優秀的 React 組件庫以及一套完整組件庫的構成。vue

1、選擇開源?仍是本身造輪子?

React 大環境裏面有不少優秀的 UI 組件庫,國內比較有名的 antDesign,國外的 Material-UI,都是比較穩定和優秀的組件庫。那麼咱們爲何還要本身去開發一套組件庫呢?緣由大體以下:node

  • 有贊各個業務線 PC 產品有獨立的設計規範,包括但不限於組件樣式、交互模式。
  • 有贊微商城、零售、美業等 PC 產品的業務場景較爲複雜,須要深度定製某些通用的組件,如 DesignSKU 組件。
  • 須要同時支撐有贊多個業務部門的 PC 產品。
  • 團隊成員以開源的模式參與組件庫的開發,期間會有不少互相的討論、碰撞,自己也是對團隊的鍛鍊過程。

2、組件庫構成

構建一個完整的組件庫須要考慮:react

  • 組件設計思路
  • 組件代碼規範
  • 組件開發流程
  • 組件測試
  • 組件維護(包括 PR / issue 管理、發包、文檔)

1. 組件設計思路

組件是對一些具備相同業務場景和交互模式代碼的抽象,組件庫首先應該保證各個組件的視覺風格和交互規範保持一致,X 組件在 A 業務場景是一個交互,在 B 業務場景是另外一個 UI 風格,這樣就沒法對 X 進行抽象,極大的增長了組件的構建成本。因此,設計組件之初,首先須要抽象和約定一套統一的視覺風格和交互規範。git

其次,組件庫的 props 定義須要具有足夠的可擴展性,並且組件內部徹底受控,保持組件具備統一的輸入和輸出,讓咱們來看一個 Button 的例子。es6

// Button is a react component of Zent
<Button
  type="primary"
  className="customer-classname"
  loading={true}
  disabled={false}
  size="large"
  onClick={this.handleClick}
>
  {children}
</Button>
複製代碼

這是一個 Button 組件,咱們定義了不少標記狀態的 props,好比 type 表示 Button 的視覺風格,size 表示尺寸,disabled 禁用,loading 狀態等,這些狀態在組件內部都不會維護 state,全部的狀態由傳入的 props 來決定,自定義 className 方便咱們作樣式自定義,children 方便咱們自定義 Button 的顯示內容。github

Button 甚至提供了a標籤的功能,只要在Button上傳入 props:href。markdown

// Button as <a>
<Button
  type="primary"
  className="customer-classname"
  href="https://www.youzan.com"
  target="_blank"
>
  有贊首頁
</Button>
複製代碼

咱們須要作幾個約定:app

  • 組件全部狀態受控於 props
  • 組件 children 支持自定義 Dom 結構
  • 不要寫死組件內部的 Dom 結構

2. 組件代碼規範

有贊前端內部組件庫,使用的是開源 lint 工具-- felint

felint 是一個集成了 eslint、stylelint、git hook 的前端代碼檢查工具。felint 爲你的項目作如下三件事:

  1. 初始化 eslint/stylelint 配置文件,不管是 react 項目、vue 項目、es5 仍是 es6 都提供了針對性的配置方案
  2. 安裝 eslint/stylelint 及其依賴到當前項目的 node_modules 裏
  3. 掛載 git 鉤子,在你提交代碼時進行強制校驗

具體使用能夠參考官方 doc -- felint 文檔地址

3. 組件開發流程

約定好組件的設計思路和代碼規範之後,接下來咱們就能夠參與開發組件了,組件庫的基本開發流程,包括如下幾點:

  • 組件初始化
  • 組件 Coding
  • 組件 Demo

Zent 裏面有一個組件初始化命令:yarn new-component,這個命令完成了組件大部分初始化工做,包括自動建立組件須要的目錄和模版代碼,添加組件 js 和 css 代碼。而後,咱們就能夠開始寫組件代碼,代碼風格和規範嚴格按照 lint 的規範編寫,若是不符合規範,是不能提交代碼的。寫完組件之後,須要寫組件 Demo 並運行,方式是本地啓動 server 來運行組件 Demo,這個能夠組件做爲組件的調試工具。

4. 組件測試

js 單元測試框架有不少,chai、jest、mocha、karma 等等,Zent 組件庫使用的是 jest + enzyme 的組合,下面來看一個例子:

// Button UI test
import { mount } from 'enzyme';

describe('Button', () => {
  it('Button UI test', () => {
    const wrapper = mount(<Button>OK</Button>);
    expect(wrapper.hasClass('zent-btn')).toBe(true);
    expect(wrapper.text()).to.equal('OK');
  });
});
複製代碼

使用 jest 作 UI 測試有侷限性,只能測試基本的 dom 結構 和樣式,一些邏輯交互沒法測到,只能覆蓋大部分的狀況。 yarn test 用來執行測試腳本,測試結果會顯示在終端。

5. 組件維護

組件平常維護佔整個組件庫生命週期的很大一部分,組件庫作起來了之後,組件功能後續會不斷迭代,也許是 bug fix,也多是 new feature,這些組件的迭代咱們經過 PR 和 issue 來管理,同時,咱們須要管理好組件的 changelog。 總的來講,組件維護主要包括:PR / issue 的處理,發包和管理 changelog。

下面以 Zent 爲例,來介紹一下 PR 規範。

PR 標題規則:[ bug fix / breaking change / new feature ] 組件名字:修改內容描述

  • 前面方括號用來區分 PR / issue 的類型:bug fix - 組件 bug 修復;breaking change - 不兼容的改動;new feature - 新功能
  • 修改內容儘量言簡意賅,總結 PR 的改動或者描述 issue
  • 描述請用中文
  • 組件名字請用英文,首字母大寫

PR 用來生成 changelog,規範的 PR 有助於生成比較清晰的 changelog,一目瞭然,來看一下 Zent 的例子:

zent-components

組件發包

組件發包只有擁有發包權限的人才能操做,Zent 是以組件庫爲單位發包的,yarn build 會將整個 Zent 的代碼打包,使用命令 yarn publish 發包,在發包以前會跑組件測試,只有測試經過之後才能發包。

組件文檔

一份好的 doc 是一個優秀組件庫的標準,良好的文檔可以提高組件庫的總體品質和好感度,願意花時間好好寫 doc 的團隊,那麼他們產出的組件庫應該也不會差到哪去,組件庫文檔維護也是組件庫生命週期裏重要的一環,有時候你甚至須要作到中英文雙語 doc。

這裏附上 Zent 組件庫的 doc 地址:Zent

3、小結

在本文中,咱們從組件的設計思路、編碼規範、開發流程、測試、平常維護這五個方面闡述瞭如何構建一個 React 組件庫,而且以 Zent 爲例講述了有贊是如何作的,任何一個組件庫都須要的通過這個生命週期,但咱們須要思考的是:如何營造一個良好的組件庫生態環境? 咱們須要想辦法讓更多的人蔘與其中,共同做爲組件庫的維護者,選擇開源是爲了給 React 生態環境作輸出,在前端組件化已經成爲了既定事實的今天,咱們不須要重複的造輪子,而是須要在組件化方面嘗試新的突破,脫離前端技術的束縛,站在工程師的高度去抽象本身手頭的代碼。組件化這條路上,咱們還有不少事情要作,Zent 只是一個開始。

相關文章
相關標籤/搜索