Skip to content

Tech upgrade

赵鹏程(珵之) edited this page Jan 12, 2024 · 38 revisions

技术升级指引

前言

Next组件库经过长期发展,已经有了很重的历史包袱,技术架构、用户体验已经全面落后于开源社区同类竞品,急需从用户开发者角度出发,进行一波技术升级,为后续的发展铺平道路。

本次升级在 1.x 的基础上进行技术性改造,不涉及组件功能的调整,完全向前兼容。计划发布 1.27.x 版本,并停止 minor 位的升级。目前已经完成项目基本结构、工程链路及部分组件的改造,发布了 1.27.2 版本,接下来需要结合社区力量,将剩余组件逐步升级上来。

升级原则

  • 向前完全兼容性
  • TS 类型明确
  • 文档清晰完备
  • 测试用例稳定有效

待改造组件列表

https://github.com/alibaba-fusion/next/issues?q=is:open+is:issue+label:%22Technical+Upgrade%22+no:assignee

升级指引

升级点

  1. 目录优化(已完成)
  • 将每个组件相关的文档、测试用例、源码都放在同一个目录下维护,以便快速地寻找相关代码
  1. TS 化
  • 全面使用 TS 语言编写,一方面在老代码类型补全过程中发现潜在问题,另一方面完善组件库类型提示,解决以前手动维护类型带来的缺失、错误类型和额外成本,再者通过静态类型检查提升组件库稳定性
  1. 文档优化
  • 一方面对存量文档进行文案优化和Demo更新,另一方面通过 TSDoc 维护组件 api,减少手动维护 api 带来的问题。
  1. 测试工具升级,用例优化
  • 一方面解决现存测试工具稳定性、兼容性问题,另一方面对存量用例进行回归改造,保证用例书写规范、目的清晰、验证有效

TS 化

1. 重命名

# 通过脚本将 components/date-picker 目录内所有的 js 文件重命名为 ts 文件
# 脚本根据文件内是否有 jsx 语法来确定文件后缀为 .tsx 还是 .ts
npm run tool:rename2ts date-picker

# 执行一次 commit,保证 git 能够正确追踪文件历史
git commit -m 'refactor(DatePicker): rename to ts'

2. 类型补全与修正

  • 组件的类型集中在 types.ts 文件内管理
  • import 不允许携带文件后缀,如:import '../../style.js'
  • 组件入口文件components/date-picker/index.ts导出规范
    • default 导出组件本身,如:export default config(DatePicker)
    • named 导出组件 Props 类型定义 {组件名大驼峰}Props,如:export type { DatePickerProps }
    • named 导出原先 components/*/index.d.ts 导出的其它类型
    • 查看示例

3. 类型校验

# 仅检查 date-picker 目录内的 TS 类型
npm run check:types date-picker

文档优化

1. 描述文档优化

针对 components/*/__docs__/{index.md,index.en-us.md} 文档内容进行优化调整,可从语义准确性、错别字、歧义、排版等角度对文案进行酌情调整

2. 组件 API 声明方式改造

由原先在组件 static propTypes 内通过 JSDoc 描述 api 的方式,改造为在组件 Props 类型中通过 TSDoc 形式描述 api 所有信息,最后在构建时解析生成到 index.md 内对应 #API 区域

这里添加了几个自定义的 TSDoc Tag 来补充说明哪些类型及哪些属性生成文档时的细节

For 类型定义

TSDoc标签 定义 类型 必填 格式示例
@api 声明该类型需要生成文档 block @api Button
@order 声明该类型在文档中的顺序 block @order 0

For 属性定义

TSDoc标签 定义 类型 必填 格式示例
@en 声明该属性的英文文档 block 未声明了 @skip 的必填 @en En description
@skip 声明该属性不需要生成文档 modifier @skip
@version 声明该属性开始支持的版本 block @version 1.27.x
@param 描述该函数属性的参数,中英文用 - 分隔 block @param name - 名称 - username
@returns 描述该函数属性的返回值,中英文用 - 分隔 block @returns 是否为空数组 - is empty array

其他说明

  • 参考 docs/index.md 文档内 API 章节,根据其内 api 的描述在对应 Props 类型中添加 TSDoc
  • 原先未在 index.md 中声明的属性,添加 @skip 标签
  • 英文文案优先参考 docs/index.en-us.md 内的
  • 过长属性描述使用 @remarks 标签承载,属性主要描述要求简短直接
  • TSDoc 内 HTML 特殊字符需要使用 \ 转义

执行 API 生成脚本检验

npm run api date-picker

Button API 示例 组件API TSDoc参考示例 TSDoc 参考: https://tsdoc.org/

测试工具升级,用例优化

示例

组件入口导出示例

参考:components/button/index.tsx

import React from 'react';
import ConfigProvider from '../config-provider';
// src/radio/types.ts 内集中放置radio相关所有类型
import type { RadioProps, RadioState, RadioShape, RadioGroupProps } from './types';
// 子组件 Group
import Group from './group';

class Radio extends React.Component<RadioProps, RadioState> {
  static Group = Group;
  // ...
  render() {}
};

// 导出组件Props,以及其他原先在 types/radio/index.d.ts 里导出的类型,例如RadioShape
export type { RadioProps, RadioGroupProps, RadioShape };

// default 导出组件实现
export default ConfigProvider.config(Radio);

TSDoc参考示例

/**
 * @api Button
 * @order 0
 */
export interface ButtonProps {
    /**
     * 按钮的类型
     * @en Typeo of button
     * @defaultValue 'normal'
     * @version 1.2.x
     */
    type?: 'primary' | 'secondary' | 'normal';

    /**
     * 点击按钮的回调
     * @en Callback of click event
     * @example
     * (event) => {}
     */
    onClick?: React.MouseEventHandler;
  
    /**
     * xxx事件回调
     * @en Callback of xxx event
     * @param arg1 - 参数1 - Arg1
     * @param arg2 - 参数2 - Arg2
     * @returns 是否xxx - isxxx
     */
    onXXX?: (arg1: boolean, arg2: string) => boolean;

    /**
     * @deprecated use xxx insteaded
     * @skip
     */
    shape?: string;
}
Clone this wiki locally