随着vue/react这类以数据驱动为主的web框架的不断完善和壮大,越来越多的前端团队开始着手搭建内部的组件库。虽然目前市面上已经有很多功能强大且完善的组件库供我们使用,比如基于react的开源组件库ant-design,material,又比如基于vue的开源组件库elementUI,iView等。
我们在开发管理系统或者中台产品时,完全可以使用这种第三方库来开发,因为首先其服务的用户群体比较小众,一般是企业或者运营人员来使用,重点在于功能和业务,所以在B端产品比较适合;另一点就是设计要求相对于C端产品会低一些,因为B端产品或者管理系统风格统一简单反而会降低使用者的学习成本。所以对于上述情况,我们完全可以使用ant-design-pro或者element-admin-vue这类集成管理框架开开发。
我们使用第三方组件库搭建一个企业级应用是完全没有问题的,但是另一方面,随着我们对用户体验以及网站性能的要求越来越高,流量及金钱,速度即王道,对于专注于做C端的企业来说,尽可能的减少用户等待才能留住更多的用户,比如我们在某宝,某东上买一个商品,结果我们花了一分钟商品列表还没有出来(形容的有点夸张),这种情况下客户可有可能直接选择某拼了。很明显像ant-design和elementUI这样的组件不适合做C端产品,因为体积太大了,除非用高性能服务器或者其他方式弥补。所以说采用轻量级组件库对于C端项目来说有以下几点好处:
但是开发组件库还是需要投入时间和成本的,毕竟这东西不是每个团队都玩的起的。说了这么多,接下来我们就来分析和实现一个团队内部的组件库吧。
图片
目前我们开发组件库的方式有很多,只要根据npm发包原则去配置就好了,我们可以用webpack自己大家一个library,也可以直接使用create-react-app/vue-cli3来快速改造一个组件库的脚手架,或者采用之前比较火且自动集成tree-shaking的rollup,这些方式都可以搭建我们组件库的脚手架。关于如何使用webpack4.0和rollup,可以参考笔者的以下几篇文章:
其实还有一种最快的方式就是直接去ant-design或者elementUI的github仓库,把代码copy下来改成自己的组件库脚手架,当然,这也不是随便就能改好的,如果想尝试这种方案,建议大家先学好typescript和webpack。
笔者这里采用的是目前比较流行的工具链umi,umi的father专门是提供组件库或者工具库打包的集成工具,我们只需要更改配置文件就能轻松搭建一款自带说明文档的组件库。笔者接下来会具来教大家如何使用它。
图片
以上是笔者画的一个简陋的分层图,我们可以看到最底层的是我们的基础视图组件,它是上层建筑的基石。对于一个包含很多子系统的复杂的项目系统来说,要想设计一个好的架构,第一步就是合理划分组件,组件的粒度拆成的足够细,这样才能最大限度的复用组件。
对于任何一个复杂系统来说,最重要的就是实现错综复杂的业务功能,但是不同模块或者子系统之间很多业务往往是相通的或者相似的,如果这个时候我们每个页面对于实现类似的业务场景都去重复去写一遍业务代码,那完全是没必要的,对于可维护性来说也是一种打击,所以基于这种场景我们的 业务组件 就很有必要出场了。我们可以把功能或者需求类似的有机体封装成一个业务组件,并对外暴露接口来实现灵活的可定制性,这样的话我们就可以再不同页面不同子系统中复用同样的逻辑和功能了。
同理,不同页面中往往有可能出现视觉或者交互完全相同或者类似的区块,为了提高可复用性和提高开发效率,我们往往会基于基础组件和业务组件再进行一次封装,让其成为一个独立的区块以便直接复用。
通过这样一层层封装,我们就逐渐搭建了一套完整的组件化系统,基于这种模式的开发往往也是一个好的前端架构的开始。但要注意一点就是高层次的组件一定会依赖低层次的组件,但是低层次的组件不可以包含高层次的组件。(听起来有点像rudex的单向数据流法则),他们的关系就好像下图:
图片
组件库的划分其实可以参考成熟组件库划分。由于业务组件和区块划分完全取决于不同公司的实际项目情况,这里不能形成一套统一的思维框架,所以我这里说的组件库划分主要指基础组件库的划分。我们先来看看antd的划分,它划分为:通用组件,布局组件,导航组件,数据录入和数据展示组件,反馈型组件和其他。elementUI的组件划分为:基础组件,表单组件,数据呈现组件,通知类组件,导航类组件和其他,这些分类都是非常合理的划分,所以我们在设计组件库时也可以参考或者直接使用,具体总结如下:
至于组件实现的设计思路,其实笔者之前也写过很多文章来做铺垫,第一要义就是需求,一切要从需求出发。不仅仅是react的组件设计,vue或者angular等都是类似的方法和思路,这里简单给大家举一个组件开发的例子—— 弹窗组件(Modal)的开发思路:
图片
图片
图片
这一步是文章的重点,我们将会了解到如何使用umi/father来搭建团队的组件库。至于umi这个前端集成解决方案,笔者从它的架构中受到了很多启发,并且基于umi+dva+react的前端开发流程应用非常广泛,感兴趣的朋友可以研究学习一下。
官方介绍就一句话:基于rollup和docz的库打包工具。它的特点主要有:
所以作为一个开箱即用的组件库打包工具,已经为我们省去了很多中间步骤,比如说组件的测试,不同环境下的模块打包,而且还支持ts和文档功能,我们只需要掌握babel和rollup的知识,就能用它轻松配置出一个强大的组件库脚手架。如果对docz不太了解的可以在docz官网学习使用非常简单,只要你对markdown和react熟悉,分分钟入门。
其实father的使用非常简单,首先我们先安装一下father:
npm install father -D
或者使用yarn安装:
yarn add father
接下来我们可以在package.json里配置如下脚本来使用:
# 打包库$ father build# 开发环境下启动文档服务$ father doc dev# 打包编译文档$ father doc build# 将文档部署到github$ father doc deploy# 组件库测试及测试覆盖率$ father test$ father test --coverage
这里拿笔者之前已经发布到npm的组件库xui——基于react的轻量级UI组件库来举例。首先我们看看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" }
当我们执行npm run dev或者yarn dev时,father自动帮我们启动了doc服务器,我们接下来就能看到我们组件的测试文档了:
图片
图片
这些内容都是我们提前写好的mdx文档,语法类似于markdown,只不过增加了对react组件的编译支持,其实使用起来很简单,我们只需要把react组件包裹在Playground容器里就好了,具体使用可以参考以下方式:
---name: Buttonroute: /Buttonorder: 3sidebar: true---import { Playground } from 'docz'import Button from './index'# Button#### 基本用法<Playground> <Button>按钮</Button><br /> <Button type="primary">按钮</Button><br /> <Button type="warning">按钮</Button><br /> <Button type="info">按钮</Button><br /> <Button type="pure">按钮</Button><br /> <Button type="primary" shape="circle">按钮的命运</Button><br /></Playground>
头部的信息我需要介绍一下:
我们根据案例可以知道mdx里面可以使用es6的导入方式来引入组件或者变量,其实还有很多配置,这里就不一一举例了,感兴趣的可以到docz官网学习。以下是官网的截图:
图片
接下来介绍我们最重要的部分,.fatherrc.js文件的配置。初始化father项目时会自动生成一个默认配置,但是大多数情况下我们都需要自定义配置,官网的配置参数也很多,可以找到适合自己团队的配置,这里我主要介绍xui组件库的配置细节。先看看配置代码:
// .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;
图片
通过以上的配置,我们就能愉快的开发组件啦。
组件说明文档是让其他人了解组件库的关键环节,包括组件库的适用范围(pc端,移动端,轻量级还是重量级),兼容浏览器的版本,设计原则和背景,以及社区生态,使用方法等。所以组件库说明文档的编写也是非常重要的,大家具体可以参考antd或者element的说明文档,可以说是写的非常专业了。如下是antd的例子:
图片
大家可以参考以上笔者整理的核心部分去写组件说明文档。
如果你在为团队开发私有组件库,那么完全不需要在意接下来笔者写的内容,但是如果你要开发一个开源的,大家都能使用的组件库,一定要注意以下几点的编写:
首先我们需要在package.json中配置github的地址:
"repository": { "type": "git", "url": "git+https://github.com:MrXujiang/xu_ui.git" }
大家可以复制以上代码改成自己的仓库地址。
其次我们需要登录进npm官网,如果你还没有账号可以直接申请一个,也很简单,然后在终端通过命令行登录。
接下来我们执行以下几个命令就能将自己的组件库打包发布到npm上了:
// 打包编译组件库yarn build// 编译组件库文档,该步骤可省略yarn build:doc// 部署组件库文档到github, 该步骤可省略yarn deploy// 发布到npm上npm publish --access public
以上的yarn命令具体实现可参考xui的package.json,也可以自己配置。经过上述步骤我们就成功将自己的组件库发布到npm上了,是不是很简单呢?
笔者已经将实现过的组件发布到npm上了,大家如果感兴趣可以直接用npm安装后使用,方式如下:
npm i @alex_xu/xui// 导入xuiimport { Button, Skeleton, Empty, Progress, Message, Tag, Switch, Drawer, Badge, Alert} from '@alex_xu/xui'
该组件库支持按需导入,我们只需要在项目里配置babel-plugin-import即可,具体配置如下:
// .babelrc"plugins": [ ["import", { "libraryName": "@alex_xu/xui", "style": true }]]
npm库截图如下:
图片
笔者本篇文章并不会将微前端架构的知识,但是既然涉及到组件库,就一定要形成一个知识闭环,笔者特意画了如下脑图,供前端朋友或者正准备走向微前端架构的团队一些参考:
本文链接:http://www.28at.com/showinfo-26-26002-0.html从0到1教你搭建前端团队的组件系统
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com
下一篇: 语聊房架构演进实践