目前的主要精力是在维护组内的业务组件库,当然也包括后续我们扩展的区块、模版、解决方案等。这篇文档主要结合我过往的项目经历,简单介绍下我对于前端物料生态的理解。
首先在我看来,从复用的颗粒度上划分物料大致为分下面几种:
- 组件;
- 区块;
- 页面模版;
- 场景化解决方案;
组件
组件作为前端物料的最小单元服务于各个业务系统。在使用上,组件既可以以组件库 / 单包的形式提供给业务系统使用,也可以按照一定的 DSL 规约服务于特定的搭建系统作为 UI 原子(UI 可视化搭建系统) / 逻辑原子(逻辑编排系统)。
从组件架构和组成形式上看,组件可以分为单包多组件(组件库)和单包单组件和两种。
这里以 antd 举例:antd 本身作为组件库以单包多组件的形式提供给开发者,而 antd 底层的每个组件又依赖于 react-component 中的一个单包单组件。
单包多组件形式的好处在于组件更聚合的呈现给使用者,并且组件间的公共依赖也可以更好的抽象复用,对于使用方来说引一个包就可以享受整包的资源。但是缺点在于某一个小小的改动也需要整个组件库整体发包。
单包单组件形式的好处在于组件见天然解耦,组件见独立发布。而缺点在于,因为每一个组件都完全物理隔离,那么对于公共依赖就需要抽离更多的基础依赖包来共享。如果单包组件存在链式依赖,对于组件开发者来说每一次发布也是不小的挑战,当然,也可以通过 MonoRepo 架构来一定程度解决。此外,如果某一个组件体积较大、逻辑较重、具有某个领域特定的复用场景,也是可以单独以单组件包的形式提供,例如:富文本编辑器、视频播放器等。
从功能上看,我们的组件又可以划分为关注视图和交互的视图型组件和关注业务逻辑的容器型组件。
容器组件
容器型组件往往用于聚合多个展示型组件,并承载一定的业务逻辑:请求接口、合并数据等等。而在容器组件的复用上,我们常常采用 render props、HOC 或者粒度更细的 hooks 来实现(视图组件也如此)。
视图组件
视图组件从业务场景的使用以及功能的划分上又进一步的可以分为 UI 组件和业务组件。
![](/qrcode.jpg)
UI 组件
首先是 UI 组件,从功能上来讲这类组件主要是作为页面上的最小单元来解决某一类单点场景,或者说,这类组件是针对某类场景在前端页面中找并集,例如 Input 、Select 等,他们最大的优点就是复用度极高、使用灵活。但是不足也与之而来,解决单点场景的 UI 组件需要组合大量的组件和业务逻辑才能生产出一个前端页面。
UI 组件一般是能够满足业界绝大部分场景的通用范式,业界往往是将这些具有通用特性的 UI 组件以组件库的形式给开发者使用,例如 AntD、ElementUI、Fusion 等。
业务组件
虽然说 UI 组件库已经能够满足绝大部分的设计、生产需求,但对于特定的场景、业务域来说往往有着自己独特的设计语言或是组件的组合模式。对于迭代速度快、项目工程资产多的中后台团队来说,每一个项目、团队都去沉淀一套相同业务域的组件资产显然是浪费人力的行为,那么此时对于当前业务域的这些组件的组合范式便可以以业务组件库的形式沉淀下来。
例如,我目前所属的广告投放领存在大量的人群、时间、区域的圈选组件,或者说中后台常见的表单联动,这些组件往往就是 input、select 等 UI 组件加上一定的业务交互逻辑和设计规范,那么我们便可以将他们以业务组件和业务组件库的形式沉淀下来。
总结起来,UI 组件是为了满足大部分生产场景的通用范式,而业务组件是为了满足某一特定业务领域的通用范式,他们都是为了解决前端页面某一单点场景。
区块
组件维度已经能够满足大部分的生产场景了,但是对于固定模式的交互场景,单靠组件仍是需要大量的重复组合工作,因此我们通过区块来解决某一块内容的复用问题。
在使用上,组件多为组件库或单包的 npm 引入。而区块由于覆盖范围更广,如果通过 npm 包的形式使用就会让使用方组合大量的 props 来使用,使得复杂度从组件的拼接变为了 props 的拼接。因此在区块维度上,我们更提倡使用源码形式使用。在传统的组件库的使用上,消费者多通过选择组件后复制展示站点的 demo 来使用,而区块由于粒度的问题源码会以多个文件的形式存在,这样对于消费者来说粘贴代码就显得繁琐,因此我们落地了物料拉取工具(cli 工具以及 vscode 插件)。
到此,在使用上,区块的生产者按照设计稿 / 交互稿生产区块源码,区块的消费者通过工具将区块源码插入到项目指定位置,并按照自己的业务逻辑删除或更新拉下来的区块源码。此外,对于更细粒度的使用,例如用惯了诸如 antd 等 UI 组件库的 demo 粘贴功能,我们也提供区块树按文件的可视化 cv 操作。
在存储上,我选择将区块物料存储在 cdn 上而不是 npm 上。首先,区块因为源码的一次使用的特征,使得区块并不需要很强的版本控制(虽然我也支持了按版本存储),消费侧也无需感知后续区块的升级。此外,cdn 的拉取在一定程度上也比 npm 包的安装快的多。此外,在区块每次发版上传 cdn 的同时,我们的依赖分析工具也会自动生成当前区块所需的依赖包及版本。
在拉取上,cli 工具 / vscode 插件识别到待安装的区块名后,内核会去 cdn 上查找 @latest 版本的区块资源并下载到消费侧指定的目标位置(当然也支持按照指定版本号拉取),区块下载完毕后,内核会根据区块的依赖以及目标项目的依赖做依赖 diff ,从而提醒消费者是否安装/更新物料依赖。
在展示站点以及本地开发上,由于我们的区块在存储上没有使用 npm ,因此我们沉淀了本地开发同步脚本以及发布同步脚本来实现工程自动化从而减少重复工作量。
到此,一个完整的区块生产/消费链路大致如下图所示:
在提效上,因为使用了源码方式引用,区块聚焦的提效范围更多在初始化项目或者页面上某块功能的单次使用,之后的维护都将和普通页面一样由开发者来维护,不存在区块更新的说法。那么痛点也与之而来,源码方式的使用使得区块的迭代和业务的升级不会有关联性,当出现整体性 UI 升级的场景会使得区块物料和业务方同时需要修改。
页面模版
模版相对于区块粒度更粗一些,他所聚焦的场景是具有固定交互逻辑的页面,一个模版又可以由多个区块、组件以及源码组成,例如:常见的中后台搜索列表页、报表分析页面等等。
在使用上,页面模版和区块的使用大同小异,甚至页面模版也可以算做复杂场景下的区块,因此这里就不过多的赘述了。此外,在展示站点上,我们专门做了一个标记物料的功能,用户可以通过该功能看到当前的模版依赖了那些物料资源,并可以前往当前物料的详情页。换个角度来说,用户也可以根据模版的物料标记看到区块组合的效果以及实际的使用场景。
在提效上,模版的粗颗粒度也就限制了它仅固定在了某个页面的快速初始化上面。并且他方面的弊端也都和区块类似。
场景化解决方案
最后就是场景化解决方案,场景化解决方案旨在基于页面模版、工程脚手架、数据管理、发布部署等能力让开发者快速基于源码开发具有固定场景的前端应用,
例如: 在中后台管理系统的场景下,我们可以使用 Ant Design Pro 来快速落地一个中后台项目。
我们也可以基于微前端解决方案来包装一个具有良好隔离、应用分治的微前端工程模版。
也可以是像 dumi、bisheng 这样专注于生产力工具静态站点展示的工程工具。
可以看到,场景化解决方案是项目层面的提效,他利用大而全的项目模版帮助开发者快速初始化一个前端工程项目。因此他的复用范围仅限在固定业务项目的工程初始化。
结语
最后总结一下:
- 组件:解决单点问题
- UI 组件:解决通用场景下的单点问题,复用率高、灵活;
- 业务组件:解决固定业务场景下的单点问题,复用率高、灵活,但不如 UI 组件:
- 区块:解决页面中某一个块内容的生产,源码使用,复用率低于组件,一次使用;
- 页面模版:解决页面级别的复用,源码使用,复用率低于区块,一次页面初始化使用;
- 场景化解决方案:解决项目级别复用,工程使用,复用率仅限于固定场景生产项目初始化;
关于前端物料资产纬度的内容就分享到这里,后面我也会沉淀一篇文章专门讲解前端物料生态下的工程自动化。