-
Notifications
You must be signed in to change notification settings - Fork 592
Tech upgrade
赵鹏程(珵之) edited this page Jan 12, 2024
·
38 revisions
Next组件库经过长期发展,已经有了很重的历史包袱,技术架构、用户体验已经全面落后于开源社区同类竞品,急需从用户
、开发者
角度出发,进行一波技术升级,为后续的发展铺平道路。
本次升级在 1.x 的基础上进行技术性改造,不涉及组件功能的调整,完全向前兼容。计划发布 1.27.x
版本,并停止 minor 位的升级。目前已经完成项目基本结构、工程链路及部分组件的改造,发布了 1.27.2
版本,接下来需要结合社区力量,将剩余组件逐步升级上来。
- 向前完全兼容性
- TS 类型明确
- 文档清晰完备
- 测试用例稳定有效
- 目录优化(已完成)
- 将每个组件相关的文档、测试用例、源码都放在同一个目录下维护,以便快速地寻找相关代码
- 全面使用 TS 语言编写,一方面在老代码类型补全过程中发现潜在问题,另一方面完善组件库类型提示,解决以前手动维护类型带来的缺失、错误类型和额外成本,再者通过静态类型检查提升组件库稳定性
- 一方面对存量文档进行文案优化和Demo更新,另一方面通过 TSDoc 维护组件 api,减少手动维护 api 带来的问题。
- 一方面解决现存测试工具稳定性、兼容性问题,另一方面对存量用例进行回归改造,保证用例书写规范、目的清晰、验证有效
# 通过脚本将 components/date-picker 目录内所有的 js 文件重命名为 ts 文件
# 脚本根据文件内是否有 jsx 语法来确定文件后缀为 .tsx 还是 .ts
npm run tool:rename2ts date-picker
# 执行一次 commit,保证 git 能够正确追踪文件历史
git commit -m 'refactor(DatePicker): rename to ts'
- 组件的类型集中在 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
导出的其它类型 - 查看示例
- default 导出组件本身,如:
# 仅检查 date-picker 目录内的 TS 类型
npm run check:types date-picker
针对 components/*/__docs__/{index.md,index.en-us.md}
文档内容进行优化调整,可从语义准确性、错别字、歧义、排版等角度对文案进行酌情调整
由原先在组件 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);
/**
* @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;
}