Skip to content
🔗 内容纲要:

构建组件库 / 工具库平台

背景介绍

基于小鱼前端现状,没有一个通用的组件和函数库平台,各个业务线在独自维护开发自己平台的组件和通用函数工具库,导致开发效率较低,没有办法统一管理组件和工具函数。

基于此,2021 年,我们考虑搭建自己的 PC 组件平台和通用工具函数库平台,方便各个业务能够快速开发和使用通用的组件和函数,避免无效的开发。

现已完成搭建的两个平台:

  1. XY-Element
  2. Toolkit

XY-Element (组件库)

现在的组件库主要针对 web 。

现状

现在已经推进并完成的相关工作:

  • 文档管理与发布
  • storybook 开发预览组件
  • 组件打包与部署
  • 生成组件模板
  • 单元测试

TODO

  • 组件库主题配置
  • 组件 UI 和交互规范
  • 基础组件开发

构架

  • 文档:dumi
  • 打包:rollup
  • 组件管理:storybook
  • 测试:jest
  • 开发语言:typescript

开发指南

  1. 从 github 拉取 xy-element 项目:xy-element
bash
git clone git@github.com:xylink-com/xy-element.git
1
  1. 初始化项目:安装依赖
bash
yarn init
1
  1. 生成目标组件
bash
yarn generate ComponentNameWithCamelCase
1

或者使用:

bash
yarn gen ComponentNameWithCamelCase
1

生成组件目录如下:

txt
Scroller
├── demo 引入文档的 demo 目录
├────── basic.tsx 默认的文档 demo 示例
├── Scroller.scss 组件样式文件
├── Scroller.stories.tsx 组件 demo 或者案例文件
├── Scroller.test.tsx 组件测试文件
├── Scroller.tsx 组件主体文件
├── Scroller.types.ts 组件类型文件
├── index.en-US.md 组件英文文档
├── index.zh-CN.md 组件中文文档
└── index.tsx 组件入口,导出相关组件和接口
1
2
3
4
5
6
7
8
9
10
11

生成组件目录结构

  1. 启动 storybook 开发组件
bash
yarn storybook
1

或者使用:

bash
yarn story
1

打开浏览器: http://localhost:6006

打开storybook

  1. 编写组件 demo

在 *.stories.tsx 中编写 demo,并且在 demo 目录中以默认导出的方式导出。 如在 demo 目录中 basic.tsx:

TS
/**
 * title: Basic Usage // 案例英文标题
 * desc: Set interval, reset interval and clear interval via setInterval. // 案例英文描述
 *
 * title.zh-CN: 基础用法 // 案例中文标题
 * desc.zh-CN: 通过 setInterval 实现的setInterval, Reset 和 Clear 定时器的用法。 // 案例中文描述
 */
// 从 storybook 中导入组件
import { SimpleContainerWithBar } from '../ContainerWithBar.stories';
// 将组件实例默认导出
export default () => <SimpleContainerWithBar />;
1
2
3
4
5
6
7
8
9
10
11

storybook 允许一个组件有多个 demo, 只要在 story.tsx 文件中 export 多个 demo 实例就可以。

demo 案例可以在文档中引入,如:

html
<code src="./demo/basic.tsx" />
1

或者也可以直接在文档中以 tsx/jsx 的方式引入代码块渲染为 demo。

更多文档的配置项参见:TSX/JSX 支持的 FrontMatter 配置项

  1. 编写文档

index.en-US.md 中编写英文文档,在 index.zh-CN.md 中编写中文文档。 文档头部的配置如下:

txt
---
title: ContainerWithBar 组件名称
nav:
  title: Components // 组件在页面顶部导航栏的归属
  path: /components // 组件在页面顶部导航栏的路由
group:
  title: Scroll // 组件在左侧导航栏的分组
  path: /scroll // 组件在左侧导航栏分组的路由
legacy: /scroll/container-with-bar // 组件的路由
---
1
2
3
4
5
6
7
8
9
10

更多文档参考项请参考:Markdown 支持的 FrontMatter 配置项

  1. 预览开发文档
bash
yarn start
1

打开浏览器: http://localhost:8000

  1. 测试组件库
bash
yarn test
1

或者:

bash
yarn test:watch
1
  1. 打包组件库
bash
yarn build
1

或者:

bash
yarn b
1
  1. 打包组件文档
bash
yarn build:doc
1

或者:

bash
yarn bd
1

快速打包组件库和静态文档:

bash
yarn go
1
  1. 发布组件库
bash
yarn pub
1

或者:

bash
yarn p
1
  1. 发布静态文档
bash
yarn pub:doc
1

或者:

bash
yarn pd
1

Q&A

  1. 生成的模板文件的详细使用方法 使用 yarn gen ExampleComponent 生成的文件如下:
  • ExampleComponent.tsx 这里写组件的主要逻辑,会相应的生成组件的模板代码,如:
ts
import React from "react";
import ExampleComponentProps from "./ExampleComponent.types";
import "./ExampleComponent.scss";

const ExampleComponent: React.FC<ExampleComponentProps> = (props) => {
 const {...restProps} = props;
 return (
   <div data-testid="ExampleComponent" {...restProps} className="" /> 
 )
};

ExampleComponent.displayName = "ExampleComponent";
export default ExampleComponent;
1
2
3
4
5
6
7
8
9
10
11
12
13

可以专注于写组件的业务逻辑。

  • ExampleComponent.scss

这里写组件样式,主题文件会自动引入。

ts
@import "src/theme.scss";
1
  • ExampleComponent.types.ts

这里写组件的类型、接口等。

ts
export default interface ExampleComponentProps {
}
1
2
  • ExampleComponent.stories.tsx

这里是组件 demo ,可以打开 storybook 看到实时的开发效果。这里会导出一个默认的 demo 。

ts
import React from "react";
import ExampleComponent from "./ExampleComponent";

export default {
    title: "ExampleComponent" // storybook 侧边导航栏标题
};

export const BasicExampleComponent = () => <ExampleComponent />;
1
2
3
4
5
6
7
8
  • ExampleComponent.test.tsx 这里是测试文件,可以使用 jest 和 testing-library 进行单元测试。
ts
import React from "react";
import { render } from "@testing-library/react";

import ExampleComponent from "./ExampleComponent";
import ExampleComponentProps from "./ExampleComponent.types";
1
2
3
4
5

这里是中英文文档,生成的文件中已经有默认的配置,写文档时只要稍作修改即可。

md
---
title: ExampleComponent
nav:
  title: Components
  path: /components
group:
  title: Example
  path: /example
legacy: /example/component-name
---

# ExampleComponent
// 组件简介

## 示例

<code src="./demo/basic.tsx" />

## 用法

\`\`\`ts

\`\`\`

### 参数

| 参数 | 描述 | 类型 | 默认值 |
| ---- | ---- | ---- | ------ |

### 接口与类型

\`\`\`ts

\`\`\`

### 工作流

#### TOFIX

#### TODO

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

默认文档中包含了实例、用法、参数、接口与类型、TODO 等项,可以介绍清楚组件的使用方法、案例和开发计划。

  • index.tsx

这个文件会帮你导出组件、组件类型,总结组件需要向外暴露的部分。

ts
import ExampleComponent from "./ExampleComponent";
import ExampleComponentProps from "./ExampleComponent.types";

export { ExampleComponentProps };
export default ExampleComponent;
1
2
3
4
5
  1. 组件和文档分别是怎样部署的?
  • 组件由 master 分支维护,分版本发布到 npm。发布方式为手动发布。
  • 文档的更新与发布:
    • 目前文档的发布方式:文档原件保存在 guide 目录,打包后在 docs 目录。打包文档后执行 yarn pd ,发布到 github-pages。
    • 计划的发布方式:开发人员不再关注文档打包和部署,开发者将分支合并至 master 后,由 GitHub action 打包项目文档,并发布到 gh-pages 分支作为静态文档发布。发布方式为自动发布,这样开发者只需关注文档编写即可。
  1. 为什么要同时使用 dumi 和 storybook?
  • storybook 开发组件很方便,但是生成静态文档不是很方便。
  • dumi 只作为文档工具来使用,即我们写的文档最后会被自动打包和发布,开发中最常使用的仍然是 storybook。
  • 后期我们可以将 storybook 的组件文档也进行发布,用户既可以在 storybook 中浏览组件列表,也可以在 dumi 中看到组件的使用方法和开发动向。
  • 开发中只启用 storybook 即可,编写文档时可以本地打开 dumi 查看文档效果。
  1. 怎么更改组件模板? 组件模板可以在 utils/templates 目录中进行修改,可以新增模板文件或者修改现有的模板。

  2. storybook 中开发的 demo 能用于文档中吗? 可以。在 demo 目录中象征性的从 story 文件中导入再默认导出 demo,然在在文档中通过 code 标签直接引用,demo 无需重复编写。 或者您也可以直接在文档中以 tsx/jsx 代码段从 story 文件中中引入 demo 并显示在文档中。

  3. 文档具体是怎么部署到 GitHub pages 的?

  • 手动部署:使用 gh-page 可手动部署本地 build 目录到远端 gh-pages 分支。

  • 使用 GitHub action 自动部署

    在项目中新建.github/workflows 目录,添加 gp-ci.yml 如下:

yaml
 name: CI

# Controls when the action will run. 
on:
  # Triggers the workflow on push or pull request events but only for the master branch
  push:
    branches: [ master ]
  pull_request:
    branches: [ master ]

  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  publishDoc:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest
    strategy:
      matrix:
        node-version: [12.x]

    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v2

      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v1
        with:
          node-version: ${{ matrix.node-version }}


      - name: Install Packages  # 安装依赖
        run: npm install && npm install yargs-parser
        
      - name: Cache node modules # 缓存依赖
        uses: actions/cache@v1
        with:
          path: node_modules
          key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
          restore-keys: |
            ${{ runner.OS }}-build-${{ env.cache-name }}-
            ${{ runner.OS }}-build-
            ${{ runner.OS }}-

      - name: Build docs # 打包文档
        run: npm run build:doc
      
      - name: Publish docs # 发布文档
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./docs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57

这时可以编写文档不用关注文档的打包与发布,直接合并到 master 分支即可,action 会自动打包和发布文档。

参见:部署文档到 github pages

  1. 开发人员需要做什么? 只需要关注组件开发和文档编写,不需要关注部署与发布。
  1. yarn gen Component
  2. yarn story
  3. 编写组件和 demo
  4. 填写文档
  5. pull request

toolkit (工具库)

Github: toolkit Docs: xy-element website Getting start: Getting Started

现状

现在已经完成的工作:

  • 工具打包与部署
  • 文档管理
  • 文档发布
  • 单元测试
  • 部分工具开发

TODO

  • 工具整理与开发
  • 完善文档

架构

  • 文档: dumi
  • 打包:rollup
  • 开发语言:typescript
  • 测试:jest

目录结构

txt
toolkit
├── LICENSE
├── README.en-US.md
├── README.md
├── _test_  // 测试目录
├── config
├── docs  // 生成静态文档
├── guide  // 文档原件
├── lib
├── package.json
├── public
├── rollup.config.js
├── src
├── tsconfig.json
└── yarn.lock
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

计划开发的工具类

工具类正在开发,没人每周开发并提交一个工具类,由团队内进行代码审核。

  • broswer: 浏览器相关,如类型检测、版本检测
  • fullscreen (event): 全屏模块
  • store:localStorage 缓存
  • time:时间格式化
  • axios:axios 封装,包括请求拦截器
  • httpclient:网络请求工具封装
  • 节流 / 防抖
  • websocket:websocket 相关方法封装
  • logger:日志模块
  • timeout/interval/requestanimation:定时器相关方法
  • emmit:事件管理模块
  • db:indexedDB 封装
  • tranlateMoney (fixed):货币转换
  • url parms:url 解析
  • mergeDeep:对象深合并
  • cloneDeep:深拷贝
  • array/object/map: 常见数据结构方法封装
  • native (native-js)(android,ios):native 模块封装

演示

Released under the MIT License.