如何搭建一个完美的组件库?
如何做一个组件库?本篇文章不会讲一个小的组件如何设计,而是会整体讲一个“逼近完美”的组件库是怎么设计的。
组件库划分
要想设计一个灵活好用的组件库,第一步就是要合理的划分组件,组件的粒度足够细,边界足够清晰,这样才能最大程度地复用组件。
从一张图介绍各种组件的区别,基础组件,也就是与业务功能无关的组件,比如 antd/fusion 中提供的组件,upload, dialog 等等这些。但是只有这些基础组件是远远不够的。
比如,你可能会经常遇到这样的场景:
- 前端开发: 设计师又造“新轮子”了, 为什么就不能本本份份使用 fusion 或者 antd 的基础样式呢?
- 设计师: “我觉得这个基础样式没有灵魂,我觉得这样比较好看”
这种时候,业务组件就有用处了。此时可以利用 fusion 或者 antd 的基础组件,进行二次封装,形成自己产品的独特组件,也称“业务独特领域的组件”。
但事实上,还是有很多场景,他可能会频繁变更,如果开发一个组件,里面的传参等等都可能会不停变更,此时就可以直接用“区块”来实现。直接提供一个组件代码模版,让使用方直接复制粘贴,然后在里面修改他的内容。
再往高一点,页面级别,也称为模版, 比如“登录页”,可能不同产品之间,这个登录页中间一部分逻辑是变化不可控的,那可以直接提供一个页面模版,供使用方直接使用, 比如 页面模版[1]。
好了, 通过上面的讲述,我们知道在什么场景下该使用什么组件,知道如何划分组件可以让我们的组件库更加灵活强大,接下来就要讲一下如何开发一个组件了。
组件开发
- 设计师: 哎,我这里的间距要从 14px 改成 16px, 然后字体颜色改成 ***
- 前端开发: 我…………
难道一个前端每天都要在这调整样式吗?那未免太无趣了…… 此时一个主题变量就很重要了。
1. 主题变量
我们可以提前跟设计师约定, 比如主字体大小多少,主颜色是什么,然后设计师出稿时按照设置的变量来出。
这样前端跟设计师之间就通过一个 scss 变量来衔接,搭建一个主题配置的网站,如下【fusion 主题配置】,在开发业务组件的时候,注入该网站配置的相关变量。
设计师可以在这里设置他想要的变量,最后生成对应的 scss 变量,如下截图:
经过下面的操作流程,在实际项目中,前端开发只需要重新编译构建项目即可修改组件样式, 真正从样式中解放出来~
好了,除了 css 样式,做一个组件还需要注意以下一些事情。
2. 如何让一个 npm 包体积最小
- umd -> esm
- 配置 peerDependencies 。。。
"peerDependencies": {
"react": ">=16.12.0",
"react-dom": ">=16.12.0"
}
如上的配置,可以让组件库下的 node_modules 不安装 react,同时指定组件库使用方需安装的 react/reactDOM 的版本。
- 配置对应的 externals
3. 文档生成
之前分享过一篇 react 文档自动生成的文章, 感兴趣可以看一下
4. commit 规范 & changelog 生成
首先,使用 husky 插件, 在 pre-commit 阶段添加钩子,限制该项目提交的 git commit 信息。
之后,我们再利用 conventional-changelog[2] 插件, 把历史 commit 信息进行筛选提炼,自动化生成统一规划的 CHANGELOG 文件。
5. 打通设计师&前端工具
如果前端埋头造轮子,相信我,你们的设计师依然不会放过你们,因为他不知道你们造了什么轮子
所以此时实现一个 sketch 插件,将实现的组件同步到 sketch 插件中,这样每次设计师就可以看着已有的组件来拖拽生成设计稿。大大减少前端&设计师的沟通。如下图:
实现上面一个完整的链路,可以大大提升前端的开发效率。不过一个公司如果想 从 0 搭建这样一套完整的组件库,务必要投入大量的人力。这时候,可以上 fusion 上看看, 上面什么都有。
参考资料
[1]
页面模版: https://ice.alibaba-inc.com/scaffold
[2]
conventional-changelog: https://www.npmjs.com/package/conventional-changelog?spm=ata.13261165.0.0.3bc056f1sAukeo
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Python正则表达式(下)
- spring boot 如何统一处理 Filter、Servlet 中的异常信息
- 10分钟理解Focal loss数学原理与Pytorch代码(翻译)
- 十分钟了解受控文本生成 1
- 数据库系统设计概述
- Java基础篇(03):流程控制语句,和算法应用
- 09 | Tornado源码分析:Future 对象
- 面向对象的7种设计原则(4)-合成/聚合复用原则
- Netty之异步通知机制
- 面向对象的7种设计原则(3)-依赖倒置原则
- Java实现旅行商最短距离
- 不是吧,阿Sir啊,可不可以不用再写finally?
- 整理得吐血了,二叉树、红黑树、B&B+树超齐全,快速搞定数据结构
- 牛客网-最小的k个数
- 牛客网-栈的压入、弹出序列