<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          從0到1教你搭建前端團(tuán)隊(duì)的組件系統(tǒng)(高級(jí)進(jìn)階必備)

          共 6958字,需瀏覽 14分鐘

           ·

          2020-02-27 23:24

          04ff6f36af99d9e1f35234e68f6d75c5.webp

          前言

          隨著vue/react這類以數(shù)據(jù)驅(qū)動(dòng)為主的web框架的不斷完善和壯大,越來(lái)越多的前端團(tuán)隊(duì)開始著手搭建內(nèi)部的組件庫(kù)。雖然目前市面上已經(jīng)有很多功能強(qiáng)大且完善的組件庫(kù)供我們使用,比如基于react的開源組件庫(kù)ant-design,material,又比如基于vue的開源組件庫(kù)elementUI,iView等。

          我們?cè)陂_發(fā)管理系統(tǒng)或者中臺(tái)產(chǎn)品時(shí),完全可以使用這種第三方庫(kù)來(lái)開發(fā),因?yàn)槭紫绕浞?wù)的用戶群體比較小眾,一般是企業(yè)或者運(yùn)營(yíng)人員來(lái)使用,重點(diǎn)在于功能和業(yè)務(wù),所以在B端產(chǎn)品比較適合;另一點(diǎn)就是設(shè)計(jì)要求相對(duì)于C端產(chǎn)品會(huì)低一些,因?yàn)锽端產(chǎn)品或者管理系統(tǒng)風(fēng)格統(tǒng)一簡(jiǎn)單反而會(huì)降低使用者的學(xué)習(xí)成本。所以對(duì)于上述情況,我們完全可以使用ant-design-pro或者element-admin-vue這類集成管理框架開開發(fā)。我們使用第三方組件庫(kù)搭建一個(gè)企業(yè)級(jí)應(yīng)用是完全沒有問題的,但是另一方面,隨著我們對(duì)用戶體驗(yàn)以及網(wǎng)站性能的要求越來(lái)越高,流量及金錢,速度即王道,對(duì)于專注于做C端的企業(yè)來(lái)說,盡可能的減少用戶等待才能留住更多的用戶,比如我們?cè)谀硨?,某東上買一個(gè)商品,結(jié)果我們花了一分鐘商品列表還沒有出來(lái)(形容的有點(diǎn)夸張),這種情況下客戶可有可能直接選擇某拼了。很明顯像ant-design和elementUI這樣的組件不適合做C端產(chǎn)品,因?yàn)轶w積太大了,除非用高性能服務(wù)器或者其他方式彌補(bǔ)。所以說采用輕量級(jí)組件庫(kù)對(duì)于C端項(xiàng)目來(lái)說有以下幾點(diǎn)好處:
          • 打包體積小,高度可控
          • 采用內(nèi)部組件庫(kù)安全性更高,防止嵌入攻擊
          • 構(gòu)建和開發(fā)更靈活,且組合型更高
          但是開發(fā)組件庫(kù)還是需要投入時(shí)間和成本的,畢竟這東西不是每個(gè)團(tuán)隊(duì)都玩的起的。說了這么多,接下來(lái)我們就來(lái)分析和實(shí)現(xiàn)一個(gè)團(tuán)隊(duì)內(nèi)部的組件庫(kù)吧。

          你將收獲

          • 如何從0搭建一個(gè)組件庫(kù)
          • 前端組件系統(tǒng)設(shè)計(jì)思路和模式
          • 組件庫(kù)的劃分及設(shè)計(jì)思路
          • 組件庫(kù)的package.json文件配置說明
          • 將組件庫(kù)部署到github并發(fā)布到npm上

          正文

          1. 開發(fā)組件庫(kù)的幾種方式


          937f6eba76d83ddd01065bf68777798c.webp目前我們開發(fā)組件庫(kù)的方式有很多,只要根據(jù)npm發(fā)包原則去配置就好了,我們可以用webpack自己大家一個(gè)library,也可以直接使用create-react-app/vue-cli3來(lái)快速改造一個(gè)組件庫(kù)的腳手架,或者采用之前比較火且自動(dòng)集成tree-shaking的rollup,這些方式都可以搭建我們組件庫(kù)的腳手架。關(guān)于如何使用webpack4.0和rollup,可以參考筆者的以下幾篇文章:

          其實(shí)還有一種最快的方式就是直接去ant-design或者elementUI的github倉(cāng)庫(kù),把代碼copy下來(lái)改成自己的組件庫(kù)腳手架,當(dāng)然,這也不是隨便就能改好的,如果想嘗試這種方案,建議大家先學(xué)好typescript和webpack。

          筆者這里采用的是目前比較流行的工具鏈umi,umi的father專門是提供組件庫(kù)或者工具庫(kù)打包的集成工具,我們只需要更改配置文件就能輕松搭建一款自帶說明文檔的組件庫(kù)。筆者接下來(lái)會(huì)具來(lái)教大家如何使用它。

          2. 前端組件系統(tǒng)設(shè)計(jì)思路和模式

          15df8f96a70e359165b6ff1db8b01d7e.webp

          以上是筆者畫的一個(gè)簡(jiǎn)陋的分層圖,我們可以看到最底層的是我們的基礎(chǔ)視圖組件,它是上層建筑的基石。對(duì)于一個(gè)包含很多子系統(tǒng)的復(fù)雜的項(xiàng)目系統(tǒng)來(lái)說,要想設(shè)計(jì)一個(gè)好的架構(gòu),第一步就是合理劃分組件,組件的粒度拆成的足夠細(xì),這樣才能最大限度的復(fù)用組件。

          對(duì)于任何一個(gè)復(fù)雜系統(tǒng)來(lái)說,最重要的就是實(shí)現(xiàn)錯(cuò)綜復(fù)雜的業(yè)務(wù)功能,但是不同模塊或者子系統(tǒng)之間很多業(yè)務(wù)往往是相通的或者相似的,如果這個(gè)時(shí)候我們每個(gè)頁(yè)面對(duì)于實(shí)現(xiàn)類似的業(yè)務(wù)場(chǎng)景都去重復(fù)去寫一遍業(yè)務(wù)代碼,那完全是沒必要的,對(duì)于可維護(hù)性來(lái)說也是一種打擊,所以基于這種場(chǎng)景我們的?業(yè)務(wù)組件?就很有必要出場(chǎng)了。我們可以把功能或者需求類似的有機(jī)體封裝成一個(gè)業(yè)務(wù)組件,并對(duì)外暴露接口來(lái)實(shí)現(xiàn)靈活的可定制性,這樣的話我們就可以再不同頁(yè)面不同子系統(tǒng)中復(fù)用同樣的邏輯和功能了。同理,不同頁(yè)面中往往有可能出現(xiàn)視覺或者交互完全相同或者類似的區(qū)塊,為了提高可復(fù)用性和提高開發(fā)效率,我們往往會(huì)基于基礎(chǔ)組件和業(yè)務(wù)組件再進(jìn)行一次封裝,讓其成為一個(gè)獨(dú)立的區(qū)塊以便直接復(fù)用。通過這樣一層層封裝,我們就逐漸搭建了一套完整的組件化系統(tǒng),基于這種模式的開發(fā)往往也是一個(gè)好的前端架構(gòu)的開始。但要注意一點(diǎn)就是高層次的組件一定會(huì)依賴低層次的組件,但是低層次的組件不可以包含高層次的組件。(聽起來(lái)有點(diǎn)像rudex的單向數(shù)據(jù)流法則),他們的關(guān)系就好像下圖:


          724ea5798521f52bc23c1132fb5934fd.webp



          3. 組件庫(kù)的劃分及設(shè)計(jì)思路

          組件庫(kù)的劃分其實(shí)可以參考成熟組件庫(kù)劃分。由于業(yè)務(wù)組件和區(qū)塊劃分完全取決于不同公司的實(shí)際項(xiàng)目情況,這里不能形成一套統(tǒng)一的思維框架,所以我這里說的組件庫(kù)劃分主要指基礎(chǔ)組件庫(kù)的劃分。我們先來(lái)看看antd的劃分,它劃分為:通用組件,布局組件,導(dǎo)航組件,數(shù)據(jù)錄入和數(shù)據(jù)展示組件,反饋型組件和其他。elementUI的組件劃分為:基礎(chǔ)組件,表單組件,數(shù)據(jù)呈現(xiàn)組件,通知類組件,導(dǎo)航類組件和其他,這些分類都是非常合理的劃分,所以我們?cè)谠O(shè)計(jì)組件庫(kù)時(shí)也可以參考或者直接使用,具體總結(jié)如下:

          • 通用型組件: 比如Button, Icon等.
          • 布局型組件: 比如Grid, Layout布局等.
          • 導(dǎo)航型組件: 比如面包屑Breadcrumb, 下拉菜單Dropdown, 菜單Menu等.
          • 數(shù)據(jù)錄入型組件: 比如form表單, Switch開關(guān), Upload文件上傳等.
          • 數(shù)據(jù)展示型組件: 比如Avator頭像, Table表格, List列表等.
          • 反饋型組件: 比如Progress進(jìn)度條, Drawer抽屜, Modal對(duì)話框等.
          • 其他業(yè)務(wù)類型
          至于組件實(shí)現(xiàn)的設(shè)計(jì)思路,其實(shí)筆者之前也寫過很多文章來(lái)做鋪墊,第一要義就是需求,一切要從需求出發(fā)。不僅僅是react的組件設(shè)計(jì),vue或者angular等都是類似的方法和思路,這里簡(jiǎn)單給大家舉一個(gè)組件開發(fā)的例子—— 彈窗組件(Modal)的開發(fā)思路:
          1. 需求分析

            8dc5d1605bd5e6669a7036d0043f6462.webp
          2. 功能設(shè)計(jì)及實(shí)現(xiàn)思路409416ea7bd8eafe9975491a6dedd833.webp
          3. 健壯性與組件測(cè)試5e8613ae2237f292ff3967ce7cc89b38.webp

            因?yàn)镸odal設(shè)計(jì)是組件設(shè)計(jì)里一個(gè)很典型的案例,如果想學(xué)習(xí)具體實(shí)現(xiàn)細(xì)節(jié),可以在讀完本文之后移步手摸手實(shí)現(xiàn)一個(gè)輕量級(jí)可擴(kuò)展的模態(tài)框(Modal)組件

          4. 從0搭建一個(gè)組件庫(kù)

          這一步是文章的重點(diǎn),我們將會(huì)了解到如何使用umi/father來(lái)搭建團(tuán)隊(duì)的組件庫(kù)。至于umi這個(gè)前端集成解決方案,筆者從它的架構(gòu)中受到了很多啟發(fā),并且基于umi+dva+react的前端開發(fā)流程應(yīng)用非常廣泛,感興趣的朋友可以研究學(xué)習(xí)一下。

          4.1?father介紹

          官方介紹就一句話:基于rollup和docz的庫(kù)打包工具。它的特點(diǎn)主要有:

          • 基于 docz 的文檔功能
          • 基于 rollup 和 babel 的組件打包功能
          • 支持 TypeScript
          • 支持 cjs、esm 和 umd 三種格式的打包
          • esm 支持生成 mjs,直接為瀏覽器使用
          • 支持用 babel 或 rollup 打包 cjs 和 esm
          • 支持多 entry
          • 支持 lerna
          • 支持 css 和 less,支持開啟 css modules
          • 支持 test
          • 支持用 prettier 和 eslint 做 pre-commit 檢查
          所以作為一個(gè)開箱即用的組件庫(kù)打包工具,已經(jīng)為我們省去了很多中間步驟,比如說組件的測(cè)試,不同環(huán)境下的模塊打包,而且還支持ts和文檔功能,我們只需要掌握babel和rollup的知識(shí),就能用它輕松配置出一個(gè)強(qiáng)大的組件庫(kù)腳手架。如果對(duì)docz不太了解的可以在docz官網(wǎng)學(xué)習(xí)使用非常簡(jiǎn)單,只要你對(duì)markdown和react熟悉,分分鐘入門。

          4.2 使用father搭建組件庫(kù)

          其實(shí)father的使用非常簡(jiǎn)單,首先我們先安裝一下father:

          npm?install?father?-D

          或者使用yarn安裝:

          yarn?add?father

          接下來(lái)我們可以在package.json里配置如下腳本來(lái)使用:

          # 打包庫(kù)$ father build
          # 開發(fā)環(huán)境下啟動(dòng)文檔服務(wù)$ father doc dev
          # 打包編譯文檔$ father doc build
          # 將文檔部署到github$ father doc deploy
          # 組件庫(kù)測(cè)試及測(cè)試覆蓋率$ father test$?father?test?--coverage

          這里拿筆者之前已經(jīng)發(fā)布到npm的組件庫(kù)xui——基于react的輕量級(jí)UI組件庫(kù)來(lái)舉例。首先我們看看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"??}

          當(dāng)我們執(zhí)行npm run dev或者yarn dev時(shí),father自動(dòng)幫我們啟動(dòng)了doc服務(wù)器,我們接下來(lái)就能看到我們組件的測(cè)試文檔了:d2f95561581ca1e2fa969fa1fdf7709c.webp1ee266f6451bbcc4e6120f46fb0cdba7.webp

          這些內(nèi)容都是我們提前寫好的mdx文檔,語(yǔ)法類似于markdown,只不過增加了對(duì)react組件的編譯支持,其實(shí)使用起來(lái)很簡(jiǎn)單,我們只需要把react組件包裹在Playground容器里就好了,具體使用可以參考以下方式:

          ---name: Buttonroute: /Buttonorder: 3sidebar: true---
          import { Playground } from 'docz'import Button from './index'
          # Button
          #### 基本用法





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

          • name 組件的名稱,也就是顯示在左部導(dǎo)航欄里的導(dǎo)航文本
          • route 組件頁(yè)面的路由
          • order 組件在導(dǎo)航條中顯示的順序
          • siderbar 當(dāng)前頁(yè)面是否顯示導(dǎo)航條
          我們根據(jù)案例可以知道m(xù)dx里面可以使用es6的導(dǎo)入方式來(lái)引入組件或者變量,其實(shí)還有很多配置,這里就不一一舉例了,感興趣的可以到docz官網(wǎng)學(xué)習(xí)。以下是官網(wǎng)的截圖:9c22bfd99d4bdab6e53f4b4cb94549f3.webp

          接下來(lái)介紹我們最重要的部分,.fatherrc.js文件的配置。初始化father項(xiàng)目時(shí)會(huì)自動(dòng)生成一個(gè)默認(rèn)配置,但是大多數(shù)情況下我們都需要自定義配置,官網(wǎng)的配置參數(shù)也很多,可以找到適合自己團(tuán)隊(duì)的配置,這里我主要介紹xui組件庫(kù)的配置細(xì)節(jié)。先看看配置代碼:

          //?.fatherrc.jsconst 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?主要用來(lái)定義組件庫(kù)的入口位置,通常我們會(huì)放在src目錄下,以下是xui項(xiàng)目中src的目錄結(jié)構(gòu):

            8c4651cd1d31215bd4de6a4b1c0dfcbd.webp4d0013d54775810138f21353f93aa286.webp

            大家可以參考一下,我們還可以在組件目錄下加測(cè)試代碼,這里就不舉例了。

          • doc?主要用來(lái)配置文檔的標(biāo)題,主題色以及根路由
          • extraBabelPlugins?主要用來(lái)配置額外的babel插件,比如組件庫(kù)的按需導(dǎo)入。xui雖然沒用用到antd,但是大家如果有基于antd二次開發(fā)業(yè)務(wù)組件或者區(qū)塊時(shí),可以按照如上配置去按需導(dǎo)入第三方組件庫(kù),這樣可以極大的降低代碼體積
          • cssModules?是否開啟css Module,這個(gè)按團(tuán)隊(duì)需求來(lái)定制,可以不用配置
          • extractCSS?是否將css抽離成單獨(dú)的css文件,這個(gè)也是看組件庫(kù)的體量,不過建議最好配置上
          • lessInBabelMode?在 babel 模式下做 less 編譯,基于 gulp-less,默認(rèn)不開啟
          • runtimeHelpers?是否把 helper 方法提取到 @babel/runtime 里,推薦開啟,能節(jié)約不少代碼體積
          • esm?是否輸出 esm 格式,以及指定 esm 格式的打包方式等,筆者這里使用babel的打包方式
          • cjs?是否輸出 cjs 格式,以及指定 cjs 格式的打包方式等,筆者這里使用babel的打包方式
          • autoprefixer?主要用來(lái)配置打包后的組件對(duì)瀏覽器的兼容版本
          通過以上的配置,我們就能愉快的開發(fā)組件啦。

          4.3 編寫組件說明文檔

          組件說明文檔是讓其他人了解組件庫(kù)的關(guān)鍵環(huán)節(jié),包括組件庫(kù)的適用范圍(pc端,移動(dòng)端,輕量級(jí)還是重量級(jí)),兼容瀏覽器的版本,設(shè)計(jì)原則和背景,以及社區(qū)生態(tài),使用方法等。所以組件庫(kù)說明文檔的編寫也是非常重要的,大家具體可以參考antd或者element的說明文檔,可以說是寫的非常專業(yè)了。如下是antd的例子:


          3a0fe47e70cd5b38dd783c2d9ef8eee1.webp

          大家可以參考以上筆者整理的核心部分去寫組件說明文檔。

          5. 組件庫(kù)的package.json文件配置說明

          如果你在為團(tuán)隊(duì)開發(fā)私有組件庫(kù),那么完全不需要在意接下來(lái)筆者寫的內(nèi)容,但是如果你要開發(fā)一個(gè)開源的,大家都能使用的組件庫(kù),一定要注意以下幾點(diǎn)的編寫:

          • name?package的包名,讓人一眼就能知道這個(gè)庫(kù)是用來(lái)做什么的
          • description?庫(kù)的描述,一個(gè)精準(zhǔn)而具體的組件庫(kù)的描述有利于人們?cè)趎pm或者github上的搜索,有點(diǎn)類似于SEO的感覺,沒錯(cuò),這就是組件庫(kù)的SEO
          • keywords?組件庫(kù)的關(guān)鍵字說明,這一點(diǎn)也很重要,直接影響者用戶對(duì)我們組件庫(kù)的搜索排名
          • homepage?組件庫(kù)的主頁(yè)地址,更有利于用戶了解組件庫(kù)的用法,功能等 完整的在線例子可以參考:xui——基于react的輕量級(jí)UI組件庫(kù)

          6. 將組件庫(kù)部署到github并發(fā)布到npm上

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

          "repository": { "type": "git", "url": "git+https://github.com:MrXujiang/xu_ui.git"??}

          大家可以復(fù)制以上代碼改成自己的倉(cāng)庫(kù)地址。

          其次我們需要登錄進(jìn)npm官網(wǎng),如果你還沒有賬號(hào)可以直接申請(qǐng)一個(gè),也很簡(jiǎn)單,然后在終端通過命令行登錄。

          接下來(lái)我們執(zhí)行以下幾個(gè)命令就能將自己的組件庫(kù)打包發(fā)布到npm上了:

          // 打包編譯組件庫(kù)yarn build
          // 編譯組件庫(kù)文檔,該步驟可省略yarn build:doc
          // 部署組件庫(kù)文檔到github, 該步驟可省略yarn deploy
          // 發(fā)布到npm上npm?publish?--access?public

          以上的yarn命令具體實(shí)現(xiàn)可參考xui的package.json,也可以自己配置。經(jīng)過上述步驟我們就成功將自己的組件庫(kù)發(fā)布到npm上了,是不是很簡(jiǎn)單呢?

          筆者已經(jīng)將實(shí)現(xiàn)過的組件發(fā)布到npm上了,大家如果感興趣可以直接用npm安裝后使用,方式如下:

          npm i @alex_xu/xui
          // 導(dǎo)入xuiimport { Button, Skeleton, Empty, Progress, Message, Tag, Switch, Drawer, Badge, Alert}?from?'@alex_xu/xui'

          該組件庫(kù)支持按需導(dǎo)入,我們只需要在項(xiàng)目里配置babel-plugin-import即可,具體配置如下:

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

          npm庫(kù)截圖如下:ba906a029ac75d71ad3a227b62a1e7ea.webp

          組件系統(tǒng)與微前端架構(gòu)初探

          筆者本篇文章并不會(huì)將微前端架構(gòu)的知識(shí),但是既然涉及到組件庫(kù),就一定要形成一個(gè)知識(shí)閉環(huán),筆者特意畫了如下腦圖,供前端朋友或者正準(zhǔn)備走向微前端架構(gòu)的團(tuán)隊(duì)一些參考:



          c436a3579a0b165ae98c49752003a714.webp




          推薦閱讀




          我的公眾號(hào)能帶來(lái)什么價(jià)值?(文末有送書規(guī)則,一定要看)

          每個(gè)前端工程師都應(yīng)該了解的圖片知識(shí)(長(zhǎng)文建議收藏)

          為什么現(xiàn)在面試總是面試造火箭?

          瀏覽 196
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲免费在线播放 | 久操成人毛片 | 国产在线精品播放 | 欧美日韩黄色片在线看 | 中圆A1变臉性爱免费视频在线 |