从0到1教你搭建前端团队的组件系统(高级进阶必备)
前言
随着vue/react这类以数据驱动为主的web框架的不断完善和壮大,越来越多的前端团队开始着手搭建内部的组件库。虽然目前市面上已经有很多功能强大且完善的组件库供我们使用,比如基于react的开源组件库ant-design,material,又比如基于vue的开源组件库elementUI,iView等。
-
打包体积小,高度可控 -
采用内部组件库安全性更高,防止嵌入攻击 -
构建和开发更灵活,且组合型更高
你将收获
-
如何从0搭建一个组件库 -
前端组件系统设计思路和模式 -
组件库的划分及设计思路 -
组件库的package.json文件配置说明 -
将组件库部署到github并发布到npm上
正文
1. 开发组件库的几种方式
其实还有一种最快的方式就是直接去ant-design或者elementUI的github仓库,把代码copy下来改成自己的组件库脚手架,当然,这也不是随便就能改好的,如果想尝试这种方案,建议大家先学好typescript和webpack。
笔者这里采用的是目前比较流行的工具链umi,umi的father专门是提供组件库或者工具库打包的集成工具,我们只需要更改配置文件就能轻松搭建一款自带说明文档的组件库。笔者接下来会具来教大家如何使用它。
2. 前端组件系统设计思路和模式
以上是笔者画的一个简陋的分层图,我们可以看到最底层的是我们的基础视图组件,它是上层建筑的基石。对于一个包含很多子系统的复杂的项目系统来说,要想设计一个好的架构,第一步就是合理划分组件,组件的粒度拆成的足够细,这样才能最大限度的复用组件。
3. 组件库的划分及设计思路
组件库的划分其实可以参考成熟组件库划分。由于业务组件和区块划分完全取决于不同公司的实际项目情况,这里不能形成一套统一的思维框架,所以我这里说的组件库划分主要指基础组件库的划分。我们先来看看antd的划分,它划分为:通用组件,布局组件,导航组件,数据录入和数据展示组件,反馈型组件和其他。elementUI的组件划分为:基础组件,表单组件,数据呈现组件,通知类组件,导航类组件和其他,这些分类都是非常合理的划分,所以我们在设计组件库时也可以参考或者直接使用,具体总结如下:
-
通用型组件: 比如Button, Icon等. -
布局型组件: 比如Grid, Layout布局等. -
导航型组件: 比如面包屑Breadcrumb, 下拉菜单Dropdown, 菜单Menu等. -
数据录入型组件: 比如form表单, Switch开关, Upload文件上传等. -
数据展示型组件: 比如Avator头像, Table表格, List列表等. -
反馈型组件: 比如Progress进度条, Drawer抽屉, Modal对话框等. -
其他业务类型
需求分析
-
功能设计及实现思路 -
健壮性与组件测试 因为Modal设计是组件设计里一个很典型的案例,如果想学习具体实现细节,可以在读完本文之后移步手摸手实现一个轻量级可扩展的模态框(Modal)组件
4. 从0搭建一个组件库
这一步是文章的重点,我们将会了解到如何使用umi/father来搭建团队的组件库。至于umi这个前端集成解决方案,笔者从它的架构中受到了很多启发,并且基于umi+dva+react的前端开发流程应用非常广泛,感兴趣的朋友可以研究学习一下。
4.1 father介绍
官方介绍就一句话:基于rollup和docz的库打包工具。它的特点主要有:
-
基于 docz 的文档功能 -
基于 rollup 和 babel 的组件打包功能 -
支持 TypeScript -
支持 cjs、esm 和 umd 三种格式的打包 -
esm 支持生成 mjs,直接为浏览器使用 -
支持用 babel 或 rollup 打包 cjs 和 esm -
支持多 entry -
支持 lerna -
支持 css 和 less,支持开启 css modules -
支持 test -
支持用 prettier 和 eslint 做 pre-commit 检查
4.2 使用father搭建组件库
其实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"
}
这些内容都是我们提前写好的mdx文档,语法类似于markdown,只不过增加了对react组件的编译支持,其实使用起来很简单,我们只需要把react组件包裹在Playground容器里就好了,具体使用可以参考以下方式:
---
name: Button
route: /Button
order: 3
sidebar: 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>
头部的信息我需要介绍一下:
-
name 组件的名称,也就是显示在左部导航栏里的导航文本 -
route 组件页面的路由 -
order 组件在导航条中显示的顺序 -
siderbar 当前页面是否显示导航条
接下来介绍我们最重要的部分,.fatherrc.js文件的配置。初始化father项目时会自动生成一个默认配置,但是大多数情况下我们都需要自定义配置,官网的配置参数也很多,可以找到适合自己团队的配置,这里我主要介绍xui组件库的配置细节。先看看配置代码:
// .fatherrc.js
const 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;
entry 主要用来定义组件库的入口位置,通常我们会放在src目录下,以下是xui项目中src的目录结构:
大家可以参考一下,我们还可以在组件目录下加测试代码,这里就不举例了。
-
doc 主要用来配置文档的标题,主题色以及根路由 -
extraBabelPlugins 主要用来配置额外的babel插件,比如组件库的按需导入。 xui虽然没用用到antd,但是大家如果有基于antd二次开发业务组件或者区块时,可以按照如上配置去按需导入第三方组件库,这样可以极大的降低代码体积 -
cssModules 是否开启css Module,这个按团队需求来定制,可以不用配置 -
extractCSS 是否将css抽离成单独的css文件,这个也是看组件库的体量,不过建议最好配置上 -
lessInBabelMode 在 babel 模式下做 less 编译,基于 gulp-less,默认不开启 -
runtimeHelpers 是否把 helper 方法提取到 @babel/runtime 里,推荐开启,能节约不少代码体积 -
esm 是否输出 esm 格式,以及指定 esm 格式的打包方式等,笔者这里使用babel的打包方式 -
cjs 是否输出 cjs 格式,以及指定 cjs 格式的打包方式等,笔者这里使用babel的打包方式 -
autoprefixer 主要用来配置打包后的组件对浏览器的兼容版本
4.3 编写组件说明文档
组件说明文档是让其他人了解组件库的关键环节,包括组件库的适用范围(pc端,移动端,轻量级还是重量级),兼容浏览器的版本,设计原则和背景,以及社区生态,使用方法等。所以组件库说明文档的编写也是非常重要的,大家具体可以参考antd或者element的说明文档,可以说是写的非常专业了。如下是antd的例子:
大家可以参考以上笔者整理的核心部分去写组件说明文档。
5. 组件库的package.json文件配置说明
如果你在为团队开发私有组件库,那么完全不需要在意接下来笔者写的内容,但是如果你要开发一个开源的,大家都能使用的组件库,一定要注意以下几点的编写:
-
name package的包名,让人一眼就能知道这个库是用来做什么的 -
description 库的描述,一个精准而具体的组件库的描述有利于人们在npm或者github上的搜索,有点类似于SEO的感觉,没错,这就是组件库的SEO -
keywords 组件库的关键字说明,这一点也很重要,直接影响者用户对我们组件库的搜索排名 -
homepage 组件库的主页地址,更有利于用户了解组件库的用法,功能等 完整的在线例子可以参考: xui——基于react的轻量级UI组件库
6. 将组件库部署到github并发布到npm上
"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 i @alex_xu/xui
// 导入xui
import {
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 }]
]
组件系统与微前端架构初探
最后
如果对于react/vue组件设计原理不熟悉的,可以参考我的之前写的组件设计系列文章:
笔者已经将组件库发布到npm上了, 大家可以通过npm安装的方式体验组件.
如果大家是vue技术栈,笔者还是极力推荐使用vue-cli来搭建组件库的,至于如何搭建vue组件库,笔者后期有时间会详细的出一篇文章来介绍。
如果觉得文章还可以,就点个在看支持一下作者吧