Monorepo風(fēng)格的組件工程搭建示例詳解
Monorepo概念
隨著各種技術(shù)的發(fā)展和超級(jí)應(yīng)用的出現(xiàn),人們開始考慮怎么才能將所有的小應(yīng)用都集成在一個(gè)大項(xiàng)目中,特別是在這些項(xiàng)目互相影響時(shí),在實(shí)現(xiàn)過(guò)程中,工程師們最關(guān)注的兩點(diǎn)是:項(xiàng)目功能分離 和 避免重復(fù)代碼。
如果將每個(gè)功能作為獨(dú)立的項(xiàng)目打包,隨著業(yè)務(wù)的發(fā)展,項(xiàng)目會(huì)越來(lái)越多,根本沒法管理,項(xiàng)目與項(xiàng)目之間的協(xié)作也會(huì)越來(lái)越困難,所以Monorepo的概念并產(chǎn)生了。
在Monorepo中我們可以在一個(gè)項(xiàng)目下進(jìn)行功能拆分,他們互相獨(dú)立不影響,但是又可以通過(guò)引用來(lái)達(dá)到互相協(xié)助。
Monorepo的優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
- 簡(jiǎn)化依賴的管理。
- 跨組合作更加方便。
- 代碼復(fù)用簡(jiǎn)單。
缺點(diǎn):
- 項(xiàng)目構(gòu)建時(shí)間過(guò)長(zhǎng)。
- 版本信息雜糅不清晰。
我也會(huì)基于Monorepo的方式搭建屬于自己的組件庫(kù)工程。
項(xiàng)目工程的搭建
技術(shù)選型
- 基于
pnpm的Monorepo工程,項(xiàng)目打包工具vite、gulp,使用sass處理樣式。 Vue組件寫法會(huì)支持Jsx和template的方式。項(xiàng)目支持Typescript。lint規(guī)范的接入,prettier的格式化統(tǒng)一,husky的卡點(diǎn)校驗(yàn)。- 組件單元測(cè)試使用
vitest+happy-dom。
基于以上的技術(shù)開始搭建我們的項(xiàng)目。
項(xiàng)目的大概結(jié)構(gòu)
// vb-design
|—— config //放置一些腳本
|—— examples //存放演示包
|—— demo
|—— taro-demo
...
|—— packages //存放npm庫(kù)的包
|—— hooks
|—— icon
|—— ui-h5
|—— ui-taro
...
.eslintignore
.eslintrc.js
.gitignore
.lintstagedrc.cjs
.npmrc
.prettierrc.cjs
package.json
pnpm-workspace.yaml
README.md
tsconfig.root.json
...
項(xiàng)目配置
Monerepo工程的起步
pnpm搭建Monorepo是非常簡(jiǎn)單的,只需要我們配置pnpm-workspace.yaml文件即可。具體的配置可參考pnpm-workspace.yaml | pnpm
lint、prettier、eslint的接入
lint、prettier、eslint的配置大部人應(yīng)該都很熟練了,在這我就不一一貼代碼說(shuō)明了。還不清楚的小伙伴可參考我的代碼或者找篇相關(guān)的教程自己跟著試試。
統(tǒng)一開發(fā)環(huán)境
開發(fā)環(huán)境的統(tǒng)一,主要是統(tǒng)一Node版本和pnpm,我們可以通過(guò)在package.json中配置一些字段來(lái)統(tǒng)一開發(fā)環(huán)境。
1、限制Node版本和pnpm通過(guò)配置volta和engines限制Node和pnpm的版本
//package.json
"volta": {
"node": "16.13.0"
},
"engines": {
"node": "16.13.0",
"pnpm": ">=6"
}
2、限制項(xiàng)目只能通過(guò)pnpm初始化依賴
//package.json
"scripts": {
"preinstall": "npx only-allow pnpm",
}
packages子包搭建
對(duì)于子包的搭建,不會(huì)詳細(xì)地一一講解,需要深入了解的可以自行到源代碼里看。
ui-h5搭建
- 目錄結(jié)構(gòu)設(shè)計(jì)
//ui-h5
components //組件目錄
|—— Button
|—— demo //demo演示存放目錄
|—— base.vue
...
|—— index.md //組件使用文檔
|—— index.scss //組件樣式
|—— index.ts //vue組件
|—— index.taro.ts //taro組件
|—— Icon
...
style //公共樣式存放
|—— index.scss
...
ui.h5.ts //vue組件對(duì)外暴露
ui.taro.ts //taro組件對(duì)外暴露
為了開發(fā)方便,把vue端、taro端的組件都放在該包下,以及examples需要的演示文檔和demo也放在該包下。至于各端寫好的組件、demo、演示文檔是怎么使用,后續(xù)會(huì)說(shuō)明。
- 構(gòu)建產(chǎn)物
// dist
components //單個(gè)組件
|—— Button
|—— index.scss
|—— index.css
|—— index.js
|—— index.taro.js
|—— Icon
...
style
|—— index.scss
...
types
|——
...
style.css
vb-ui.es.js
vu-ui.umd.js
vb-ui.taro.es.js
vb-ui.taro.umd.js
ui-taro搭建
該包其實(shí)沒有做更多的事情,只是初始化之后把package.json做了相關(guān)配置。最重要的地方是在根目錄下的package.json配置了腳本,在ui-h5包構(gòu)建之后,通過(guò)腳本copy了該包需要的東西。
- 腳本文件都在根目錄
config里
icon搭建
在ui-h5中,Icon組件的設(shè)計(jì)支持了iconfont和svg的方式,這也是參考了element-ui的Icon組件設(shè)計(jì)。所以該包主要是處理svg圖標(biāo),把圖標(biāo)轉(zhuǎn)化成vue組件統(tǒng)一向外暴露的過(guò)程。
另外,我并不會(huì)用設(shè)計(jì)軟件,沒有svg可用,所以借用了字節(jié)arco-design的圖標(biāo)Arco Design Icons – Figma
hooks搭建
該包主要是一些公共方法的包,目前也沒有更多的想法,所以也只是先放著。
examples瀏覽器端演示包搭建
因?yàn)榇罱ǖ氖且苿?dòng)端組件庫(kù),所以演示包需要有兩個(gè)入口,H5端和PC端。整個(gè)搭建的過(guò)程大致是:
- 通過(guò)vite-plugin-md解析md文件。
- 通過(guò)vite-plugin-pages和vite-plugin-vue-layouts管理路由,頁(yè)面的存放路徑是在
ui-h5包下。
vite-plugin-pages和vite-plugin-vue-layouts的配置
//vite.config.js
Pages({
dirs: [
{
dir: resolve(__dirname, '../../packages/ui-h5/components'),
baseRoute: 'component',
},
],
exclude: ['**/components/*.vue'],
extensions: ['vue', 'md'],
}),
Layout({
layoutsDirs: 'src/layouts',
defaultLayout: 'preview',
})
項(xiàng)目的構(gòu)建與npm包發(fā)布
這么多的子包,打包構(gòu)建以及推送到npm是不是需要到每個(gè)子包下執(zhí)行完打包和執(zhí)推送的命令?針對(duì)這個(gè)問題pnpm官方是有解決方案的:
首先所有的子包都定義個(gè)build命令來(lái)執(zhí)行當(dāng)前包的所有打包構(gòu)建事情,最后項(xiàng)目根目錄package.json的配置如下:
//package.json
"scripts": {
"build": "pnpm --filter './packages/**' run build && pnpm run build:taro", //執(zhí)行packages下所有子包的build方法
"release": "pnpm run build && pnpm run release:only",
"release:only": "changeset publish --tag=beta --access=publish", //發(fā)布所有子包
"build:taro": "node ./config/build-taro.js",
"build:demo": "pnpm --filter './examples/**' run build"
}
上方build這個(gè)地方的配置pnpm官方有很詳細(xì)的說(shuō)明。再就是關(guān)于npm publish的,主要是通過(guò)@changesets/cli這個(gè)cli工具去解決。
changeset publish 只是一個(gè)很純凈的發(fā)包命令,手動(dòng)提升/修改版本后再 changeset publish他會(huì)將所有包都publish一次。
- 寫到這,順便再給大家說(shuō)下這個(gè)項(xiàng)目的代碼發(fā)布流吧。
- 版本號(hào)是手動(dòng)修改的。
- 通過(guò)打
tag的方式會(huì)觸發(fā)workflows去執(zhí)行打包構(gòu)建,然后publish和部署演示的demo。
很多開源的項(xiàng)目通過(guò)changeset-bot + changesets/action + @changesets/cli能玩出各種各樣的工作流。
關(guān)于單元測(cè)試
單測(cè)在開源項(xiàng)目里是不可缺少的存在,雖然我不一定會(huì)去寫單測(cè)??,但是該有的東西還是得搭起來(lái)。
Vitest是基于vite的原生快速單元測(cè)試,完全兼容Jest的Api,還能共用vite的配置。所以針對(duì)當(dāng)前項(xiàng)目使用Vitest是最快接入單元測(cè)試的方式,但是很遺憾,針對(duì)小程序端還沒有更好的接入單元測(cè)試方案。
最后
寫到這,組件庫(kù)的搭建過(guò)程也差不多了,有什么不了解的可以留言或私信我。歡迎大家提出更好的意見或想法,還有寫作水平差,有問題請(qǐng)輕噴。
最后因?yàn)闆]有一些設(shè)計(jì)規(guī)范,所以UI組件的產(chǎn)出并不會(huì)很理想。但是從0到1實(shí)現(xiàn)的過(guò)程才是重點(diǎn),這能讓我們以后在碰到相同問題時(shí)能快速解決。
相關(guān)文章
開篇:對(duì)于組件庫(kù)的思考、技術(shù)梳理
代碼倉(cāng)庫(kù):vb-design
以上就是Monorepo風(fēng)格的組件工程搭建示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Monorepo組件搭建的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue3.0 CLI - 2.3 - 組件 home.vue 中學(xué)習(xí)指令和綁定
這篇文章主要介紹了vue3.0 CLI - 2.3 - 組件 home.vue 中學(xué)習(xí)指令和綁定的相關(guān)知識(shí),本文通過(guò)實(shí)例代碼相結(jié)合的形式給大家介紹的非常詳細(xì) ,需要的朋友可以參考下2018-09-09
在vscode 中設(shè)置 vue模板內(nèi)容的方法
這篇文章主要介紹了在vscode 中設(shè)置 vue模板內(nèi)容的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-09-09

