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

隨着vue/react這類以數據驅動爲主的web框架的不斷完善和壯大,越來越多的前端團隊開始着手搭建內部的組件庫。雖然目前市面上已經有很多功能強大且完善的組件庫供我們使用,比如基於react的開源組件庫ant-design,material,又比如基於vue的開源組件庫elementUI,iView等。
我們在開發管理系統或者中臺產品時,完全可以使用這種第三方庫來開發,因爲首先其服務的用戶羣體比較小衆,一般是企業或者運營人員來使用,重點在於功能和業務,所以在B端產品比較適合;另一點就是設計要求相對於C端產品會低一些,因爲B端產品或者管理系統風格統一簡單反而會降低使用者的學習成本。所以對於上述情況,我們完全可以使用ant-design-pro或者element-admin-vue這類集成管理框架開開發。
我們使用第三方組件庫搭建一個企業級應用是完全沒有問題的,但是另一方面,隨着我們對用戶體驗以及網站性能的要求越來越高,流量及金錢,速度即王道,對於專注於做C端的企業來說,儘可能的減少用戶等待才能留住更多的用戶,比如我們在某寶,某東上買一個商品,結果我們花了一分鐘商品列表還沒有出來(形容的有點誇張),這種情況下客戶可有可能直接選擇某拼了。很明顯像ant-design和elementUI這樣的組件不適合做C端產品,因爲體積太大了,除非用高性能服務器或者其他方式彌補。所以說採用輕量級組件庫對於C端項目來說有以下幾點好處:

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

但是開發組件庫還是需要投入時間和成本的,畢竟這東西不是每個團隊都玩的起的。說了這麼多,接下來我們就來分析和實現一個團隊內部的組件庫吧。
你將收穫

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

正文

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

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

前端組件/庫打包利器rollup使用與配置實戰
基於create-react-app打包編譯自己的第三方UI組件庫併發布到npm
用 webpack 4.0 擼單頁/多頁腳手架 (jquery, react, vue, typescript)

其實還有一種最快的方式就是直接去ant-design或者elementUI的github倉庫,把代碼copy下來改成自己的組件庫腳手架,當然,這也不是隨便就能改好的,如果想嘗試這種方案,建議大家先學好typescript和webpack。
筆者這裏採用的是目前比較流行的工具鏈umi,umi的father專門是提供組件庫或者工具庫打包的集成工具,我們只需要更改配置文件就能輕鬆搭建一款自帶說明文檔的組件庫。筆者接下來會具來教大家如何使用它。
2. 前端組件系統設計思路和模式

以上是筆者畫的一個簡陋的分層圖,我們可以看到最底層的是我們的基礎視圖組件,它是上層建築的基石。對於一個包含很多子系統的複雜的項目系統來說,要想設計一個好的架構,第一步就是合理劃分組件,組件的粒度拆成的足夠細,這樣才能最大限度的複用組件。
對於任何一個複雜系統來說,最重要的就是實現錯綜複雜的業務功能,但是不同模塊或者子系統之間很多業務往往是相通的或者相似的,如果這個時候我們每個頁面對於實現類似的業務場景都去重複去寫一遍業務代碼,那完全是沒必要的,對於可維護性來說也是一種打擊,所以基於這種場景我們的 業務組件 就很有必要出場了。我們可以把功能或者需求類似的有機體封裝成一個業務組件,並對外暴露接口來實現靈活的可定製性,這樣的話我們就可以再不同頁面不同子系統中複用同樣的邏輯和功能了。
同理,不同頁面中往往有可能出現視覺或者交互完全相同或者類似的區塊,爲了提高可複用性和提高開發效率,我們往往會基於基礎組件和業務組件再進行一次封裝,讓其成爲一個獨立的區塊以便直接複用。
通過這樣一層層封裝,我們就逐漸搭建了一套完整的組件化系統,基於這種模式的開發往往也是一個好的前端架構的開始。但要注意一點就是高層次的組件一定會依賴低層次的組件,但是低層次的組件不可以包含高層次的組件。(聽起來有點像rudex的單向數據流法則),他們的關係就好像下圖:

  1. 組件庫的劃分及設計思路
    組件庫的劃分其實可以參考成熟組件庫劃分。由於業務組件和區塊劃分完全取決於不同公司的實際項目情況,這裏不能形成一套統一的思維框架,所以我這裏說的組件庫劃分主要指基礎組件庫的劃分。我們先來看看antd的劃分,它劃分爲:通用組件,佈局組件,導航組件,數據錄入和數據展示組件,反饋型組件和其他。elementUI的組件劃分爲:基礎組件,表單組件,數據呈現組件,通知類組件,導航類組件和其他,這些分類發都是非常合理的劃分,所以我們在設計組件庫時也可以參考或者直接使用,具體總結如下:

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

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

需求分析

功能設計及實現思路

健壯性與組件測試

因爲Modal設計是組件設計裏一個很典型的案例,如果想學習具體實現細節,可以在讀完本文之後移步手摸手實現一個輕量級可擴展的模態框(Modal)組件

  1. 從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

基本用法

按鈕
按鈕
按鈕
按鈕
按鈕
按鈕的命運
複製代碼頭部的信息我需要介紹一下:

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組件庫

  1. 將組件庫部署到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庫截圖如下:

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

發佈了15 篇原創文章 · 獲贊 0 · 訪問量 540
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章