从零开始搭建一个属于自己的组件库!

2022-11-30 0 515

原副标题:从头开始构筑两个属于他们的模块库!

来自:提前产业布局,作者:张翰

模块在前端合作开发中越来越重要了,合作开发人员更行业龙头、著眼于模块微观的合作开发,接着像捞虾一样完成应用机能。模块库能标准化管理模块,输入文件格式,能提升模块F83E43Se性、防止多次重复造车轮。赶快构筑他们的模块库吧,这瓜保甜!

市场需求背景

为什么要构筑模块库?

虽然业内已经有许多成熟杰出的ui库能供他们采用,也为他们解决了许多难题。但是此基础的小东西常常不能满足用户所有销售业务情景,更多这时候他们须要扩充机能来满足用户销售业务的市场需求,比方说 table 须要自订列这种的~相信这也是许多爸爸妈妈合作开发这时候的情景。

跨工程项目F83E43Se。许多这时候为了方便快捷,只是如前所述当前工程项目对模块进行伊瓦诺PCB(再说我是这种干的呵呵),接着做其它工程项目碰到同样情景时,或者copy(时常忘掉以后PCB在别的工程项目里了🌚)、或者重新干两个…常常缺乏两个统筹规划的地方,F83E43Se很不方便快捷。

模块采用文件格式。文件格式工业生产对于第一线合作开发来说可能相对比较缺乏,因为大家都无暇顾及撸销售业务,文件格式这种爱马仕省钱一点儿是一点儿。这种导致两个难题就是他们PCB的模块别人不会用、不晓得在哪里用,甚至不晓得有这么个小东西。

跨项目组资源共享发展。大多B端系统都是以 element 、 antd 等ui架构为主,如前所述各种销售业务情景,基本单厢有他们项目组的伊瓦诺PCB。其实类似的机能扩充肯定会有的是,如果有模块库把模块都集中起来,就能减少许多多次重复造车轮的劳力了!

本栏以后就时常有这种的关键点,在某个工程项目里伊瓦诺PCB了 el-select ,实现 filterable 的时搜寻快捷方式移到下拉列表中,防止多选时多个 tag 抬升了搜寻框的空间。当时是写在两个工程项目里,接着其它工程项目也碰到了这种的市场需求…我在十多个工程项目里面寻找、自述,寻回当年PCB的模块,人都麻了……

刚好最近在搞 云产品,须要提供给谢鲁瓦前台标准化的式样、产业布局规范化以网络连接,还须要 标准化扩充此基础模块的能力。于是模块库的市场需求的就这么出来了!基本想做成的就是对 element-ui/plus 、 antd 一些模块进行伊瓦诺PCB、扩充,并集成到模块库中,本栏当仁不让把市场需求从大佬手上抢过来做。

目前初步构筑起来了两个简易的模块库了,可对 element-plus 、 element-ui 的模块进行合作开发调试,且目前已经实现几个模块的扩充了~当然,第一版还是有许多工作没做完、做好,不过没关系,毕竟不能一下吃成两个胖子。更多实现、优化、还会慢慢迭代做,到这时候有空会继续分享相关的干货~

从零开始搭建一个属于自己的组件库!

本文会从模块库的 工程架构文件格式模块合作开发环境准备打包、发布进行分享,模块合作开发环境主要是 element-ui/plus 的🤣,因为本期市场需求只要满足用户 vue2 、 vue3 的中台,所以 antd 的还没有投入,只好等下期了。与其说分享,其实更是做两个记录沉淀一下,也是回顾总结~事不宜迟!开始进入主题吧,从0-1构筑两个模块库

一、工程项目架构

第一次搞模块库,仿佛走进两个新的空白领域了。作为两个没经验的小白,当然是得抄作业啦,不不不,应该是“借鉴”😜。这这时候搞个开源的工程项目来参照参照还是挺香的,于是本栏就去“学习了”element-plus工程项目[1] 的架构、代码组织方式,再结合他们的市场需求情景就开始干了。

1. Monorepo

整个工程的代码组织采用 Monorepo 的组织方式,采用工具 pnpm + workspace 来实现。所以全部工程项目都是放在一个仓库里的,包括文件格式、模块。

工程具体分为以下几块,以 文件格式模块库为两大类进行分块:

文件格式工程(docs)

安装指引

模块采用文件格式( elm 、 elp 、 antd )

模块合作开发文件格式

模块库(packages)

element-plus

element-ui

ant-design

voice-components

其中 voice-components 本栏是打算用来做 adapt层用的,因为文件格式工具用了 VitePress (后面会讲),它只能支持 vue3 的模块,所以 vue2 、 react 的模块须要做一层适配,这一块是预留的,暂时能不关注。

从零开始搭建一个属于自己的组件库!

image.png

第一版比较简单,后续如果沉淀出一些工具、打包脚本等,也会再扩充几个工程项目放进去 workspace 里。所以目前就先这种吧,用着先~

2. 文件格式工程项目结构

抄作业抄作业,这部分跟 element-plus 基本是一致的。

index.md 。!!顾名思义,文件格式首页~

.vitepress 目录:文件格式站点工具配置相关,这个后面再展开~

zh-CN目录:文件格式md文件

components: 模块采用文件格式.md 。模块的 采用demo案例代码,相关 配置说明

guide: 模块库指引文件格式.md 。包括模块的安装指南、合作开发指南

public目录:相关静态资源目录。 css 、 image 等

build目录:放点他们实现的构建脚本、vite插件啥的

从零开始搭建一个属于自己的组件库!

image.png 3. 模块库结构

这部分跟 element-plus 也是基本一致的,具体大家能参照他们的实现,这里就记录个大概,粗略带过吧。

每两个ui架构的结构都一样,以其中两个为例记录:

模块工程项目入口—— 根index 。导出当前工程项目须要导出的所有模块(可按需引入)。并导出全局安装方法。( Vue.use(VcComponents) )可全局注册 export* from./components

exportdefault{

install } 复制代码 2. components:- 入口文件:index。导出所有模块。 js export * from … export * from … export * from … 复制代码 “` – 存放全部模块,以模块名作为文件夹名。3. 模块文件夹(以button为例):- 入口文件:index。导出当前模块,并包装 install 方法(主要用于 Vue.use 调用时进行全局注册)。- 模块文件。实现模块扩充的伊瓦诺PCB。(这里建议扩充模块时保留模块的原来用法,这种能降低采用这时候的学习成本)

从零开始搭建一个属于自己的组件库!

image.png 二、模块库工具

这里不会面面俱到,只记录一些用到的核心工具以及核心的用法~就算不是特别细粒度,相信大家要他们动手搞的这时候也难不倒你们的!!本栏这么菜都一样搞,你们肯定都行!

1. 文件格式站点工具—— VitePress

对于模块库来说,文件格式能说是最关键的一环了,没有文件格式的模块库不是真的模块库~这里本栏用了几分钟去调研(根本就没怎么调研),最终决定采用VitePress[2] 作为文件格式站点工具,目前用的版本是 1.0.0-alpha.4 。(呵呵哈大家不要害怕alpha版,用着没啥毛病)

采用下来 基本配置用法官方文件格式[3] 中都能找到,已经满足用户当前的采用情景了~大家也要采用的话,花点时间去搓一搓就好,整个文件格式站点构筑不算难,毕竟只要能跑起来就能慢慢调整慢慢搞。

核心配置(都放在 .vitepress 目录下):

配置文件: .vitepress 根目录的 config 文件。其实没有特别多的配置,主要就是 导航栏菜单栏而已。

exportdefaultdefineConfig({

title: voice-ui, deion: , base, head: [ [ link, { rel: icon, href: /images/favicon.ico } ] ], themeConfig: { logo: /images/favicon.ico, nav, // 配置导航栏 sidebar, // 配置侧边菜单栏 footer // 配置页脚 } }) 复制代码 “`

nav 配置导航栏配置( 文件格式链接[4] )

exportdefault[

{ text: 指南, link: , activeMatch: }, { text: element-plus, link: , activeMatch: }, { text: element-ui, link: , activeMatch: }, { text: ant-design, link: , activeMatch: } ] 复制代码 “`

sidebar 配置侧边菜单栏( 文件格式链接[5] )。具体配置太多就不全贴出来了,这里的配置在文件格式中都能找到。如下这种配置就是两个 nav 路由对应两个 sidebar 菜单。

exportdefault{

/zh-CN/guide/: [ { text: 安装, items: [ { text: element-plus, link: }, … ] }, { text: 合作开发人员指南, items: … } ] } 复制代码 “`

大概的效果如下,不同nav对应各自的侧边栏菜单:![image.png](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/965ca66b0c364079b9efb9e5e9113f8d~tplv-k3u1fbpfcp-zoom-in-crop-mark:3024:0:0:0.awebp?)

![image.png](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/7723fd9b09ad4ac4b1e0507b0d3076ac~tplv-k3u1fbpfcp-zoom-in-crop-mark:3024:0:0:0.awebp?)

/theme/index 中自订义主题 & 全局注册 vue3 模块

具体配置参照文件格式[6] 。这里的仅是本栏的基本配置~ import{ App } fromvue

importTheme fromvitepress/theme

import../../public/css/customStyle.css// 自订义的主题色文件

importelement-plus/dist/index.css

importelement-plus/theme-chalk/dark/css-vars.css

importVcComponent from@voice-ui/voice-components// 上文提到的adapt层,导出vue3的模块

exportdefault{

…Theme,

enhanceApp ({ app }: { app: App}) {

app.use(VcComponent) // 进行模块注册,这种他们能直接在 markdown 中采用模块啦!

}

}

复制代码

customStyle.css 文件其实就是对 VitePress 的一些 css变量进行自订义重写👇 :root{

–vc-primary-color: #295dfa;

}

:root{

–vp-c-brand: var(–vc-primary-color); /* 自订义 VitePress 的主题色 */

}

复制代码

2. 打包工具—— Vite

提到这个必须提一嘴:合作开发真丝滑!是的,包括各工程项目的 dev 、 build 都是采用 Vite 完成。其实这个没什么好说的,大家可能用得比我都熟~所以这里只简单带一带用了什么机能~

用到的 vue2、 vue3 插件( 官方文件格式戳[7] ):

underfin/vite-plugin-vue2

@vitejs/plugin-vue

打包配置——库模式。基本的都有了。 es 、 cjs 、 umd 、 iife 。( 官方文件格式戳[8] ,具体下文会讲)

配置 alias 。各模块在 dev、prod环境中相互引用( 官方文件格式戳[9] ,具体下文会讲)

配置 external 。( vite配置[10] ; rollup配置[11] )

第一版差不多就这些了,配置上还是比较简单的。基本能满足用户 dev合作开发、build打包 市场需求。

三、合作开发环境

因为采用的 VitePress 支持在 markdown 中 直接采用 vue3 模块 ,所以 vue2 、 vue3 、 react 相关的合作开发环境有所不同。如前所述此, element-plus 的合作开发环境就没有单独搞了,直接在 docs 工程项目中进行模块合作开发。

1. vue3 + element-plus 合作开发环境

这里也是直接抄作业的,模仿 element-plus 的实现。核心做法:

包装 element-plus模块 一层 install 方法

在 VitePress 中进行 全局注册

在 md文件 中直接采用注册好的模块,能直接在文件格式中进行合作开发调试

大概的代码思路:

给模块对象添加 install 方法

import{ withInstall } from../../utils

importButton from./button.vue

exportconstVcButton = withInstall(Button)

exportdefaultVcButton

export* from./

复制代码

install方法:接收两个 Vue3 对象,用 Vue.component 进行模块注册

exportconstwithInstall = comp=> {

comp.install = app => { app.component(comp.name, comp) } return comp } 复制代码 “`

文件格式工程项目中,在 .vitepress/theme/index.ts 中进行全局注册(上文也有提到)

exportdefault{

enhanceApp ({ app }: {app: App}) { // 这里能拿到 app ,也就是Vue3的app // VcButton在这里进行全局注册 app.use(VcButton) // app.use 就会调用 VcButton的install方法 } } 复制代码 “`

md中直接采用注册好的模块

# Button 按钮

这是两个按钮

# Element-plus

## Button

< vc-button/>

复制代码

接着就能在页面上看到了,并且是有热更新的!这种他们直接合作开发调试即可了。

image.png 2. vue2 + element-ui 合作开发环境

vue2 、 react 的合作开发环境实现思路大致相同(react的这次还没搞,以vue2为例就好),就是在当前工程项目中用vite启动两个devServer进行合作开发,就跟普通的工程项目合作开发是一样的。

根目录建两个 index.html ,指定入口

搞个demo目录,其实就是Vue工程项目,newVue完后挂载到dom上。如下:

在 demo-xxx 的vue文件中导入合作开发的模块进行试用、调试。

页面效果如下:

react的虽然还没做,但是具体思路也是跟vue2一样的,在react他们的工程项目中起服务进行模块的合作开发调试~后续做了的话会补充进这里~

四、模块打包、发布

目前的打包、发布实现得比较简单。大概是标准化打包,接着进到每个目录中去进去npm发布,目前也是只发布在内部的npm中。

1. 标准化打包

为了打包方便快捷,且契合当前发布平台的特性,在整个工程项目的根目录中 package.json 的 s 中进行了 命令整合。这里后续可能会用脚本的方式去实现,因为可能在打包的这时候要处理一些其它的逻辑。目前第一版大概如下:

{

“s”: {

“build”: “pnpm run build:elp && pnpm run build:elu && pnpm run build:shared”,

“build:elp”: “pnpm run -C packages/element-plus build”,

“build:elu”: “pnpm run -C packages/element-ui build”,

“build:shared”: “pnpm run -C packages/shared build”,

“release”: “node s/release.ts”

}

}

复制代码

2. 模块库的打包配置

上文打包工具哪里有提到过,目前是最简单版的,打出 es、cjs、umd、iife 格式的包,而且要external掉第三方库。大概配置:

exportdefaultdefineConfig(async({ command, mode }) => {

return{

plugins: [ createVuePlugin ],

build: {

rollupOptions: {

external: [ element-ui, vue]

},

lib: {

entry: path.resolve(__dirname, ./components/index.js),

name: voiceUi,

fileName: vc-element-ui,

formats: [ es, cjs, umd, iife]

}

},

resolve: {

alias: awaitalias

}

}

})

复制代码

3. npm发布

其实 npm包 安装只是其中一种方式,该模块库后续还会新增模块联邦——MF的网络连接方式,这个会在后续进行扩充,到这时候做了的话再补充一下或者再写一篇文章吧~

目前的npm发包这时候用了个脚本,基本就是进到每个目录下去执行以下更新版本好,接着执行 npm publish 。(这里的脚本会结合他们发布平台的一些能力去写的,所以就不贴出来了,大致思路就是这种)

五、合作开发时一些注意点1. Vue版本冲突导致启动服务、打包失败

因为是采用 Monorepo 代码组织方式,所以整个工程项目难免会出现依赖包重合(版本不同)的难题。就比方说这整个工程项目中既装了 Vue3 、也装了 Vue2 ,可能起工程项目时会报错:

Vue packages version mismatch:

[email protected]

[email protected]

复制代码

但是仔细检查发现当前工程项目的 node_modules 中的 vue 和 vue-compiler 是同版本的,而且是在当前工程中执行的启动、打包。查了个 issus ,在pnpm文件格式中找到了相关的解决方案:

image.png

具体文件格式地址: pnpm—shared-workspace-lockfile[12]

配置了这个文件后难题就解决了~

2. 配置alias解决入口难题

模块库 打包后的入口合作开发时的入口其实是有点 不一致的,所以如果他们合作开发中直接 import xxx from 模块库名称 这种导入模块是会有难题的,毕竟一般情况下他们的入口是配置打包完之后的产物的入口的(一般是dist、lib目录下的index)。

image.png

出于这点,配置个alias就很好解决难题了,因为许多地方用到,本栏直接就封成了个函数:

exportasyncfunctionalias: Promise< Array< Alias>> {

constprojectPath = packagesPath

constdirArr = awaitfsPromises.readdir(projectPath)

returndirArr.map( packagePath=> {

return{

find: newRegExp( `^@voice-ui\/${packagePath}(\/(dist))?$` ),

replacement: path.join(projectPath, `/ ${packagePath}/index` )

}

})

}

复制代码

大概作用就是把入口从 dist 下面换到当前工程的对应工程项目下的index入口。

3. 式样隔离

docs工程项目中用的 VitePress ,他会有一些他们的式样控制,可能会影响到他们须要在文件格式中展示的模块。刚好本栏就碰到了这么两个情况:

image.png

如图所示,table的式样变得很奇怪。本栏并没有对式样有做什么处理,就是element-plus的table。用审查元素看了下,主要是 VitePress 也有他们的table的式样,影响到 el-table 的表现了。

他们能通过重写式样解决,但这种在其它的如 antd 、 element-ui 的模块放进来的这时候也会有难题。所以最好还是把式样进行隔离。呵呵哈,其实写到这里的这时候,本栏还没有实现式样隔离,毕竟给大伙写文章更重要嘛!!

本栏有个大概想法是用 webComponent 去隔离,这只好做完了再写出来了😝,让大家留个念想。

写在最后

其实模块库这个小东西真是早有早好,如果当前项目组还没有的是话,赶紧搞两个吧。本栏以前也没意识去搞这个小东西(还是太菜了),所以做了许多多次重复的劳动。每做一些新工程项目,或者参与别人的工程项目,时常想用一些他们以后PCB的模块,都很麻烦,有这时候为了不想切来切去,直接就动手写了。现在想想,要是那这时候就做了个模块库该多好啊~其实做个简单版的也不是很难,如果是只须要关注一种前端架构的那就更简单了,要考虑的小东西更少。把整个模块库搭出来之后,还能找其它爸爸妈妈一起资源共享,一起维护,不断强大他们项目组的模块库,大家一起受益~

真的!还没有的是赶紧搭!这瓜保甜。

— EOF —

推荐↓↓↓

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务