從0到1教你搭建前端團隊的組件系統(高級進階必備)

前言

隨着vue/react這類以數據驅動爲主的web框架的不斷完善和壯大,愈來愈多的前端團隊開始着手搭建內部的組件庫。雖然目前市面上已經有不少功能強大且完善的組件庫供咱們使用,好比基於react的開源組件庫ant-design,material,又好比基於vue的開源組件庫elementUI,iView等。javascript

咱們在開發管理系統或者中臺產品時,徹底可使用這種第三方庫來開發,由於首先其服務的用戶羣體比較小衆,通常是企業或者運營人員來使用,重點在於功能和業務,因此在B端產品比較適合;另外一點就是設計要求相對於C端產品會低一些,由於B端產品或者管理系統風格統一簡單反而會下降使用者的學習成本。因此對於上述狀況,咱們徹底可使用ant-design-pro或者element-admin-vue這類集成管理框架開開發。css

咱們使用第三方組件庫搭建一個企業級應用是徹底沒有問題的,可是另外一方面,隨着咱們對用戶體驗以及網站性能的要求愈來愈高,流量及金錢,速度即王道,對於專一於作C端的企業來講,儘量的減小用戶等待才能留住更多的用戶,好比咱們在某寶,某東上買一個商品,結果咱們花了一分鐘商品列表尚未出來(形容的有點誇張),這種狀況下客戶可有可能直接選擇某拼了。很明顯像ant-design和elementUI這樣的組件不適合作C端產品,由於體積太大了,除非用高性能服務器或者其餘方式彌補。因此說採用輕量級組件庫對於C端項目來講有如下幾點好處:前端

  • 打包體積小,高度可控
  • 採用內部組件庫安全性更高,防止嵌入攻擊
  • 構建和開發更靈活,且組合型更高

可是開發組件庫仍是須要投入時間和成本的,畢竟這東西不是每一個團隊都玩的起的。說了這麼多,接下來咱們就來分析和實現一個團隊內部的組件庫吧。vue

你將收穫

  • 如何從0搭建一個組件庫
  • 前端組件系統設計思路和模式
  • 組件庫的劃分及設計思路
  • 組件庫的package.json文件配置說明
  • 將組件庫部署到github併發布到npm上

正文

1. 開發組件庫的幾種方式

目前咱們開發組件庫的方式有不少,只要根據npm發包原則去配置就行了,咱們能夠用webpack本身你們一個library,也能夠直接使用create-react-app/vue-cli3來快速改造一個組件庫的腳手架,或者採用以前比較火且自動集成tree-shaking的rollup,這些方式均可以搭建咱們組件庫的腳手架。關於如何使用webpack4.0和rollup,能夠參考筆者的如下幾篇文章:

其實還有一種最快的方式就是直接去ant-design或者elementUI的github倉庫,把代碼copy下來改爲本身的組件庫腳手架,固然,這也不是隨便就能改好的,若是想嘗試這種方案,建議你們先學好typescript和webpack。java

筆者這裏採用的是目前比較流行的工具鏈umi,umi的father專門是提供組件庫或者工具庫打包的集成工具,咱們只須要更改配置文件就能輕鬆搭建一款自帶說明文檔的組件庫。筆者接下來會具來教你們如何使用它。node

2. 前端組件系統設計思路和模式

以上是筆者畫的一個簡陋的分層圖,咱們能夠看到最底層的是咱們的基礎視圖組件,它是上層建築的基石。對於一個包含不少子系統的複雜的項目系統來講,要想設計一個好的架構,第一步就是合理劃分組件,組件的粒度拆成的足夠細,這樣才能最大限度的複用組件。

對於任何一個複雜系統來講,最重要的就是實現錯綜複雜的業務功能,可是不一樣模塊或者子系統之間不少業務每每是相通的或者類似的,若是這個時候咱們每一個頁面對於實現相似的業務場景都去重複去寫一遍業務代碼,那徹底是不必的,對於可維護性來講也是一種打擊,因此基於這種場景咱們的 業務組件 就頗有必要出場了。咱們能夠把功能或者需求相似的有機體封裝成一個業務組件,並對外暴露接口來實現靈活的可定製性,這樣的話咱們就能夠再不一樣頁面不一樣子系統中複用一樣的邏輯和功能了。react

同理,不一樣頁面中每每有可能出現視覺或者交互徹底相同或者相似的區塊,爲了提升可複用性和提升開發效率,咱們每每會基於基礎組件和業務組件再進行一次封裝,讓其成爲一個獨立的區塊以便直接複用。jquery

經過這樣一層層封裝,咱們就逐漸搭建了一套完整的組件化系統,基於這種模式的開發每每也是一個好的前端架構的開始。但要注意一點就是高層次的組件必定會依賴低層次的組件,可是低層次的組件不能夠包含高層次的組件。(聽起來有點像rudex的單向數據流法則),他們的關係就好像下圖: webpack

3. 組件庫的劃分及設計思路

組件庫的劃分其實能夠參考成熟組件庫劃分。因爲業務組件和區塊劃分徹底取決於不一樣公司的實際項目狀況,這裏不能造成一套統一的思惟框架,因此我這裏說的組件庫劃分主要指基礎組件庫的劃分。咱們先來看看antd的劃分,它劃分爲:通用組件,佈局組件,導航組件,數據錄入和數據展現組件,反饋型組件和其餘。elementUI的組件劃分爲:基礎組件,表單組件,數據呈現組件,通知類組件,導航類組件和其餘,這些分類發都是很是合理的劃分,因此咱們在設計組件庫時也能夠參考或者直接使用,具體總結以下:css3

  • 通用型組件: 好比Button, Icon等.
  • 佈局型組件: 好比Grid, Layout佈局等.
  • 導航型組件: 好比麪包屑Breadcrumb, 下拉菜單Dropdown, 菜單Menu等.
  • 數據錄入型組件: 好比form表單, Switch開關, Upload文件上傳等.
  • 數據展現型組件: 好比Avator頭像, Table表格, List列表等.
  • 反饋型組件: 好比Progress進度條, Drawer抽屜, Modal對話框等.
  • 其餘業務類型

至於組件實現的設計思路,其實筆者以前也寫過不少文章來作鋪墊,第一要義就是需求,一切要從需求出發。不只僅是react的組件設計,vue或者angular等都是相似的方法和思路,這裏簡單給你們舉一個組件開發的例子—— 彈窗組件(Modal)的開發思路:

  1. 需求分析
  2. 功能設計及實現思路
  3. 健壯性與組件測試
    由於Modal設計是組件設計裏一個很典型的案例,若是想學習具體實現細節,能夠在讀完本文以後移步手摸手實現一個輕量級可擴展的模態框(Modal)組件

4. 從0搭建一個組件庫

這一步是文章的重點,咱們將會了解到如何使用umi/father來搭建團隊的組件庫。至於umi這個前端集成解決方案,筆者從它的架構中受到了不少啓發,而且基於umi+dva+react的前端開發流程應用很是普遍,感興趣的朋友能夠研究學習一下。

4.1 father介紹

官方介紹就一句話:基於rollup和docz的庫打包工具。它的特色主要有:

  • 基於 docz 的文檔功能
  • 基於 rollup 和 babel 的組件打包功能
  • 支持 TypeScript
  • 支持 cjs、esm 和 umd 三種格式的打包
  • esm 支持生成 mjs,直接爲瀏覽器使用
  • 支持用 babel 或 rollup 打包 cjs 和 esm
  • 支持多 entry
  • 支持 lerna
  • 支持 css 和 less,支持開啓 css modules
  • 支持 test
  • 支持用 prettier 和 eslint 作 pre-commit 檢查

因此做爲一個開箱即用的組件庫打包工具,已經爲咱們省去了不少中間步驟,好比說組件的測試,不一樣環境下的模塊打包,並且還支持ts和文檔功能,咱們只須要掌握babel和rollup的知識,就能用它輕鬆配置出一個強大的組件庫腳手架。若是對docz不太瞭解的能夠在docz官網學習使用很是簡單,只要你對markdown和react熟悉,分分鐘入門。

4.2 使用father搭建組件庫

其實father的使用很是簡單,首先咱們先安裝一下father:

npm install father -D
複製代碼

或者使用yarn安裝:

yarn add father
複製代碼

接下來咱們能夠在package.json裏配置以下腳原本使用:

# 打包庫
$ father build

# 開發環境下啓動文檔服務
$ father doc dev

# 打包編譯文檔
$ father doc build

# 將文檔部署到github
$ father doc deploy

# 組件庫測試及測試覆蓋率
$ father test
$ father test --coverage
複製代碼

這裏拿筆者以前已經發布到npm的組件庫xui——基於react的輕量級UI組件庫來舉例。 首先咱們看看xui的package.json中的script腳本如何配置的:

"scripts": {
    "dev": "npx --max_old_space_size=8096 father doc dev --host 0.0.0.0",
    "build": "father build",
    "build:doc": "father doc build",
    "deploy": "father doc deploy"
  }
複製代碼

當咱們執行npm run dev或者yarn dev時,father自動幫咱們啓動了doc服務器,咱們接下來就能看到咱們組件的測試文檔了:

這些內容都是咱們提早寫好的mdx文檔,語法相似於markdown,只不過增長了對react組件的編譯支持,其實使用起來很簡單,咱們只須要把react組件包裹在Playground容器裏就行了,具體使用能夠參考如下方式:

---
name: Button
route: /Button
order: 3
sidebar: true ---

import { Playground } from 'docz'
import Button from './index'

# Button

#### 基本用法
<Playground>
 <Button>按鈕</Button><br />
 <Button type="primary">按鈕</Button><br />
 <Button type="warning">按鈕</Button><br />
 <Button type="info">按鈕</Button><br />
 <Button type="pure">按鈕</Button><br />
 <Button type="primary" shape="circle">按鈕的命運</Button><br />
</Playground>
複製代碼

頭部的信息我須要介紹一下:

  • name 組件的名稱,也就是顯示在左部導航欄裏的導航文本
  • route 組件頁面的路由
  • order 組件在導航條中顯示的順序
  • siderbar 當前頁面是否顯示導航條

咱們根據案例能夠知道mdx裏面可使用es6的導入方式來引入組件或者變量,其實還有不少配置,這裏就不一一舉例了,感興趣的能夠到docz官網學習。如下是官網的截圖:

接下來介紹咱們最重要的部分, .fatherrc.js文件的配置。初始化father項目時會自動生成一個默認配置,可是大多數狀況下咱們都須要自定義配置,官網的配置參數也不少,能夠找到適合本身團隊的配置,這裏我主要介紹 xui組件庫的配置細節。先看看配置代碼:

// .fatherrc.js
const options = {
  entry: 'src/index.js',
  doc: {
    title: 'xu_ui',
    themeConfig: { mode: 'light' },
    base: '/xu_ui'
  },
  extraBabelPlugins: [
      ['babel-plugin-import', {
          libraryName: 'antd',
          libraryDirectory: 'es',
          style: true,
      }]
  ],
  // cssModules: true,
  extractCSS: true,
  lessInBabelMode: true,
  runtimeHelpers: true,
  esm: 'babel', 
  cjs: 'babel',
  autoprefixer: {
      browsers: ['ie>9', 'Safari >= 6'],
  }
};

export default options;
複製代碼
  • entry 主要用來定義組件庫的入口位置,一般咱們會放在src目錄下,如下是xui項目中src的目錄結構:
    你們能夠參考如下,咱們還能夠在組件目錄下加測試代碼,這裏就不舉例了。
  • doc 主要用來配置文檔的標題,主題色以及根路由
  • extraBabelPlugins 主要用來配置額外的babel插件,好比組件庫的按需導入。xui雖然沒用用到antd,可是你們若是有基於antd二次開發業務組件或者區塊時,能夠按照如上配置去按需導入第三方組件庫,這樣能夠極大的下降代碼體積
  • cssModules 是否開啓css Module,這個按團隊需求來定製,能夠不用配置
  • extractCSS 是否將css抽離成單獨的css文件,這個也是看組件庫的體量,不過建議最好配置上
  • lessInBabelMode 在 babel 模式下作 less 編譯,基於 gulp-less,默認不開啓
  • runtimeHelpers 是否把 helper 方法提取到 @babel/runtime 裏,推薦開啓,能節約很多代碼體積
  • esm 是否輸出 esm 格式,以及指定 esm 格式的打包方式等,筆者這裏使用babel的打包方式
  • cjs 是否輸出 cjs 格式,以及指定 cjs 格式的打包方式等,筆者這裏使用babel的打包方式
  • autoprefixer 主要用來配置打包後的組件對瀏覽器的兼容版本

經過以上的配置,咱們就能愉快的開發組件啦。

4.3 編寫組件說明文檔

組件說明文檔是讓其餘人瞭解組件庫的關鍵環節,包括組件庫的適用範圍(pc端,移動端,輕量級仍是重量級),兼容瀏覽器的版本,設計原則和背景,以及社區生態,使用方法等。因此組件庫說明文檔的編寫也是很是重要的,你們具體能夠參考antd或者element的說明文檔,能夠說是寫的很是專業了。以下是antd的例子:

你們能夠參考以上筆者整理的核心部分去寫組件說明文檔。

5. 組件庫的package.json文件配置說明

若是你在爲團隊開發私有組件庫,那麼徹底不須要在乎接下來筆者寫的內容,可是若是你要開發一個開源的,你們都能使用的組件庫,必定要注意如下幾點的編寫:

  • name package的包名,讓人一眼就能知道這個庫是用來作什麼的
  • description 庫的描述,一個精準而具體的組件庫的描述有利於人們在npm或者github上的搜索,有點相似於SEO的感受,沒錯,這就是組件庫的SEO
  • keywords 組件庫的關鍵字說明,這一點也很重要,直接影響者用戶對咱們組件庫的搜索排名
  • homepage 組件庫的主頁地址,更有利於用戶瞭解組件庫的用法,功能等 完整的在線例子能夠參考: xui——基於react的輕量級UI組件庫

6. 將組件庫部署到github併發布到npm上

首先咱們須要在package.json中配置github的地址:

"repository": {
    "type": "git",
    "url": "git+https://github.com:MrXujiang/xu_ui.git"
  }
複製代碼

你們能夠複製以上代碼改爲本身的倉庫地址。

其次咱們須要登陸進npm官網,若是你尚未帳號能夠直接申請一個,也很簡單,而後在終端經過命令行登陸。

接下來咱們執行如下幾個命令就能將本身的組件庫打包發佈到npm上了:

// 打包編譯組件庫
yarn build

// 編譯組件庫文檔,該步驟可省略
yarn build:doc

// 部署組件庫文檔到github, 該步驟可省略
yarn deploy

// 發佈到npm上
npm publish --access public
複製代碼

以上的yarn命令具體實現可參考xui的package.json,也能夠本身配置。通過上述步驟咱們就成功將本身的組件庫發佈到npm上了,是否是很簡單呢?

筆者已經將實現過的組件發佈到npm上了,你們若是感興趣能夠直接用npm安裝後使用,方式以下:

npm i @alex_xu/xui

// 導入xui
import { 
  Button, Skeleton, Empty, Progress,
  Message, Tag, Switch, Drawer, Badge, Alert
} from '@alex_xu/xui'
複製代碼

該組件庫支持按需導入,咱們只須要在項目裏配置babel-plugin-import便可,具體配置以下:

// .babelrc
"plugins": [
  ["import", { "libraryName": "@alex_xu/xui", "style": true }]
]
複製代碼

npm庫截圖以下:

組件系統與微前端架構初探

筆者本篇文章並不會將微前端架構的知識,可是既然涉及到組件庫,就必定要造成一個知識閉環,筆者特地畫了以下腦圖,供前端朋友或者正準備走向微前端架構的團隊一些參考:

最後

若是對於react/vue組件設計原理不熟悉的,能夠參考個人以前寫的組件設計系列文章:

筆者已經將組件庫發佈到npm上了, 你們能夠經過npm安裝的方式體驗組件.

若是你們是vue技術棧,筆者仍是極力推薦使用vue-cli來搭建組件庫的,至於如何搭建vue組件庫,筆者後期有時間會詳細的出一篇文章來介紹。

若是想獲取組件設計系列完整源碼, 或者想學習更多H5遊戲, webpacknodegulpcss3javascriptnodeJScanvas數據可視化等前端知識和實戰,歡迎在公號《趣談前端》加入咱們的技術羣一塊兒學習討論,共同探索前端的邊界。

更多推薦

相關文章
相關標籤/搜索