从0到1教你搭建前端团队的组件系统(高级进阶必备)

前言

随着vue/react这类以数据驱动为主的web框架的不断完善和壮大,愈来愈多的前端团队开始着手搭建内部的组件库。虽然目前市面上已经有不少功能强大且完善的组件库供咱们使用,好比基于react的开源组件库ant-design,material,又好比基于vue的开源组件库elementUI,iView等。javascript

咱们在开发管理系统或者中台产品时,彻底可使用这种第三方库来开发,由于首先其服务的用户群体比较小众,通常是企业或者运营人员来使用,重点在于功能和业务,因此在B端产品比较适合;另外一点就是设计要求相对于C端产品会低一些,由于B端产品或者管理系统风格统一简单反而会下降使用者的学习成本。因此对于上述状况,咱们彻底可使用ant-design-pro或者element-admin-vue这类集成管理框架开开发。css

咱们使用第三方组件库搭建一个企业级应用是彻底没有问题的,可是另外一方面,随着咱们对用户体验以及网站性能的要求愈来愈高,流量及金钱,速度即王道,对于专一于作C端的企业来讲,尽量的减小用户等待才能留住更多的用户,好比咱们在某宝,某东上买一个商品,结果咱们花了一分钟商品列表尚未出来(形容的有点夸张),这种状况下客户可有可能直接选择某拼了。很明显像ant-design和elementUI这样的组件不适合作C端产品,由于体积太大了,除非用高性能服务器或者其余方式弥补。因此说采用轻量级组件库对于C端项目来讲有如下几点好处:前端

  • 打包体积小,高度可控
  • 采用内部组件库安全性更高,防止嵌入攻击
  • 构建和开发更灵活,且组合型更高

可是开发组件库仍是须要投入时间和成本的,毕竟这东西不是每一个团队都玩的起的。说了这么多,接下来咱们就来分析和实现一个团队内部的组件库吧。vue

你将收获

  • 如何从0搭建一个组件库
  • 前端组件系统设计思路和模式
  • 组件库的划分及设计思路
  • 组件库的package.json文件配置说明
  • 将组件库部署到github并发布到npm上

正文

1. 开发组件库的几种方式

目前咱们开发组件库的方式有不少,只要根据npm发包原则去配置就行了,咱们能够用webpack本身你们一个library,也能够直接使用create-react-app/vue-cli3来快速改造一个组件库的脚手架,或者采用以前比较火且自动集成tree-shaking的rollup,这些方式均可以搭建咱们组件库的脚手架。关于如何使用webpack4.0和rollup,能够参考笔者的如下几篇文章:

其实还有一种最快的方式就是直接去ant-design或者elementUI的github仓库,把代码copy下来改为本身的组件库脚手架,固然,这也不是随便就能改好的,若是想尝试这种方案,建议你们先学好typescript和webpack。java

笔者这里采用的是目前比较流行的工具链umi,umi的father专门是提供组件库或者工具库打包的集成工具,咱们只须要更改配置文件就能轻松搭建一款自带说明文档的组件库。笔者接下来会具来教你们如何使用它。node

2. 前端组件系统设计思路和模式

以上是笔者画的一个简陋的分层图,咱们能够看到最底层的是咱们的基础视图组件,它是上层建筑的基石。对于一个包含不少子系统的复杂的项目系统来讲,要想设计一个好的架构,第一步就是合理划分组件,组件的粒度拆成的足够细,这样才能最大限度的复用组件。

对于任何一个复杂系统来讲,最重要的就是实现错综复杂的业务功能,可是不一样模块或者子系统之间不少业务每每是相通的或者类似的,若是这个时候咱们每一个页面对于实现相似的业务场景都去重复去写一遍业务代码,那彻底是不必的,对于可维护性来讲也是一种打击,因此基于这种场景咱们的 业务组件 就颇有必要出场了。咱们能够把功能或者需求相似的有机体封装成一个业务组件,并对外暴露接口来实现灵活的可定制性,这样的话咱们就能够再不一样页面不一样子系统中复用一样的逻辑和功能了。react

同理,不一样页面中每每有可能出现视觉或者交互彻底相同或者相似的区块,为了提升可复用性和提升开发效率,咱们每每会基于基础组件和业务组件再进行一次封装,让其成为一个独立的区块以便直接复用。jquery

经过这样一层层封装,咱们就逐渐搭建了一套完整的组件化系统,基于这种模式的开发每每也是一个好的前端架构的开始。但要注意一点就是高层次的组件必定会依赖低层次的组件,可是低层次的组件不能够包含高层次的组件。(听起来有点像rudex的单向数据流法则),他们的关系就好像下图: webpack

3. 组件库的划分及设计思路

组件库的划分其实能够参考成熟组件库划分。因为业务组件和区块划分彻底取决于不一样公司的实际项目状况,这里不能造成一套统一的思惟框架,因此我这里说的组件库划分主要指基础组件库的划分。咱们先来看看antd的划分,它划分为:通用组件,布局组件,导航组件,数据录入和数据展现组件,反馈型组件和其余。elementUI的组件划分为:基础组件,表单组件,数据呈现组件,通知类组件,导航类组件和其余,这些分类发都是很是合理的划分,因此咱们在设计组件库时也能够参考或者直接使用,具体总结以下:css3

  • 通用型组件: 好比Button, Icon等.
  • 布局型组件: 好比Grid, Layout布局等.
  • 导航型组件: 好比面包屑Breadcrumb, 下拉菜单Dropdown, 菜单Menu等.
  • 数据录入型组件: 好比form表单, Switch开关, Upload文件上传等.
  • 数据展现型组件: 好比Avator头像, Table表格, List列表等.
  • 反馈型组件: 好比Progress进度条, Drawer抽屉, Modal对话框等.
  • 其余业务类型

至于组件实现的设计思路,其实笔者以前也写过不少文章来作铺垫,第一要义就是需求,一切要从需求出发。不只仅是react的组件设计,vue或者angular等都是相似的方法和思路,这里简单给你们举一个组件开发的例子—— 弹窗组件(Modal)的开发思路:

  1. 需求分析
  2. 功能设计及实现思路
  3. 健壮性与组件测试
    由于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 检查

因此做为一个开箱即用的组件库打包工具,已经为咱们省去了不少中间步骤,好比说组件的测试,不一样环境下的模块打包,并且还支持ts和文档功能,咱们只须要掌握babel和rollup的知识,就能用它轻松配置出一个强大的组件库脚手架。若是对docz不太了解的能够在docz官网学习使用很是简单,只要你对markdown和react熟悉,分分钟入门。

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"
  }
复制代码

当咱们执行npm run dev或者yarn dev时,father自动帮咱们启动了doc服务器,咱们接下来就能看到咱们组件的测试文档了:

这些内容都是咱们提早写好的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 当前页面是否显示导航条

咱们根据案例能够知道mdx里面可使用es6的导入方式来引入组件或者变量,其实还有不少配置,这里就不一一举例了,感兴趣的能够到docz官网学习。如下是官网的截图:

接下来介绍咱们最重要的部分, .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上

首先咱们须要在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

// 导入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 }]
]
复制代码

npm库截图以下:

组件系统与微前端架构初探

笔者本篇文章并不会将微前端架构的知识,可是既然涉及到组件库,就必定要造成一个知识闭环,笔者特地画了以下脑图,供前端朋友或者正准备走向微前端架构的团队一些参考:

最后

若是对于react/vue组件设计原理不熟悉的,能够参考个人以前写的组件设计系列文章:

笔者已经将组件库发布到npm上了, 你们能够经过npm安装的方式体验组件.

若是你们是vue技术栈,笔者仍是极力推荐使用vue-cli来搭建组件库的,至于如何搭建vue组件库,笔者后期有时间会详细的出一篇文章来介绍。

若是想获取组件设计系列完整源码, 或者想学习更多H5游戏, webpacknodegulpcss3javascriptnodeJScanvas数据可视化等前端知识和实战,欢迎在公号《趣谈前端》加入咱们的技术群一块儿学习讨论,共同探索前端的边界。

更多推荐

相关文章
相关标签/搜索