1
头图

前言

随着时间的推进,业务组件也逐渐丰富起来,我们开始搭建组件库,编写组件文档的烦恼就随之而来。

这里分享下我选取组件文档工具的经历,最终以 Docusaurus 为基础,搭建了一套开箱即用的 React 组件文档工具。

此工具经过了两年时间的沉淀也是比较稳定,所以分享出来给有需要的人员使用,直接体验可看 react-doc-starter 这个项目。

实现的细节可以看这篇文章,手把手教你快速搭建React组件库

组件库文档工具的对比

从 0 到 1 搭建一个全新的组件库文档工具不是最优的选择,本人先在网上搜寻一些已有的解决方案。
业务项目技术栈是基于 React,UI 库使用的是 Antd,下面是一些方案的汇总和分析:

  • bisheng,Antd 官网是基于 bisheng 改造的,Antd 官网看起来是很不错,但是基于 bisheng,是需要做很多定制化的处理,不能开箱即用,上手难度相对大。
  • Gitbook,大家基本都了解,gitbook2 还支持 github 在线读取生成,但是无法支持组件 demo 的展示。
  • Gatsby,拥有丰富的插件生态,但是学习成本较高,更适合搭建门户类的网站。
  • VuePress,Vue 官方文档使用的文档工具,开箱即用,简单使用,但是不是 React 技术栈。
  • Docz,基于 Gatsby,开箱即用,支持 mdx,是一款比较适合的组件文档工具。
  • Docusaurus,开箱即用,是 facebook 团队推出的,支持 mdx,也适合搭建 React 组件文档,create-react-app 目前的官方文档是使用 Docusaurus。

工具选取的曲折之路

Docz 的尝试

2020 年初的时候,选取了 Docz,因为 Docz 开箱即用,支持 mdx 语法,提供便捷的 Props 和 Playgroud 组件。

Props 组件可读取组件的注释生成 API,Playgroud 组件可以在 mdx 文件中运行 Demo 组件,同时可以查看运行的代码,例子如下:

---
name: Button
route: /
---
​
import { Playground, Props } from 'docz'
import { Button } from './'
​
# Button
​
<Props of={Button} />
​
## Basic usage
​
<Playground>
  <Button>Click me</Button>
  <Button kind="secondary">Click me</Button>
</Playground>

经过一番折腾之后,借鉴 Antd 官网的样式,效果如下:

image-20220628145052723.png

使用 Docz 后遇到的一些问题

你以为这样就解决了组件文档上的问题吗?并没有,随着组件的增加,文档的变多,docz 开发启动时间和打包时间越来越长,甚至达到了 5 分钟以上。

5 分钟如果是首次那也能勉强接受,但是新建一个文件,服务出错,又需要重新启动服务,然后等待。。。

后来组件开发由 JavaScript 转 TypeScript,虽然 Docz 官方是支持 TypeScript,但是尝试迁移过去的时候,发现比较耗时间。

使用 Docz 遇到以下问题:

  • 组件文档变多之后,服务启动和打包时间有点久,开发效率有影响
  • 文档迁移 TypeScript 的成本相对高,除开 Demo 和 md 文件可大部分复用,文档工具基本需要从头再来。
  • 不支持类库模式的文档快捷生成
  • Playground 组件中代码无法使用独立文件

    import { Playground } from 'docz'
    import { Counter } from './Counter'
    ​
    # Counter
    ​
    <Playground>
      {() => {
        const [counter, setCounter] = React.useState(0)
        return (
          <Counter
            value={counter}
            onChange={() => setCounter(counter => counter+1)}
          />
        )
      }}
    </Playground>

Docz 的代替方案 docusaurus

2020 年初的时候,选取了 Docz,也没留意到 Docusaurus。后来 Docz 启动服务开发文档的时间越来越久,同时决定由 JavaScript 转 TypeScript,2020 年中旬本人开始寻找 Docz 的代替方案。

经过多方的查找,并没有找到合适的可代替 Docz 的方案。最终 Docusaurus 进入了我的视线, 经过深入了解,Docusaurus 使用相对简单(个人理解就是 React 界的 VuePress), 支持 mdx,同时拥有强大的可拓展性。

但是 Docusaurus 并不支持类似 Docz 的 Props 和 Playground 组件,不支持便捷生成 API ,也不能同时展示 Demo 组件效果和代码,还需要经过一些处理才能达类似 Docz 用法的效果。

对 Docz 的 Playground 和 Props 组件思考

首先看下 Docz 的 Playground 和 Props 组件的使用方式:

---
name: Alert
menu: Components
---
​
import { Playground, Props } from 'docz'
import { Alert } from './Alert'
​
# Alert
​
## Properties
​
<Props of={Alert} />
​
## Basic usage
​
<Playground>
  <Alert>Some message</Alert>
</Playground>
​
## Using different kinds
​
<Playground>
  <Alert kind="info">Some message</Alert>
  <Alert kind="positive">Some message</Alert>
  <Alert kind="negative">Some message</Alert>
  <Alert kind="warning">Some message</Alert>
</Playground>
​

鉴于上面的使用方式,有两点思考:

  • 能不能直接使用 Playground 和 Props 组件,而无需 import ?
  • Playground 能不能通过路径引用 Demo 文件来实现展示组件效果和代码?

其实是可以的,通过 webpack loader 的方式,本人实现了 PropsTableCodeShow 两个组件(其实可以理解为 jsx 的语法糖),下面介绍下这两个组件。

PropsTable 组件
<PropsTable src="$components/Table" showDescriptionOnSummary />

PropsTable 默认只读取 export default 的组件注释,注释规则需要满足 react-docgen 的注释方式,详细的例子可看 react-doc-starter 这个项目。

效果如下图所示:

image-20220701192418716.png

CodeShow 组件
<CodeShow file="$demo/ProContent/Basic.tsx" />
<CodeShow fileList={['$demo/ProContent/Basic.tsx', '$demo/ProContent/Basic.module.less']} />

之所以不叫 Playground 是因为 CodeShow 组件不支持动态修改代码,同时 CodeShow 组件还支持多文件的代码展示(例子的渲染只渲染第一个文件的代码),详细的例子可看 react-doc-starter 这个项目。

效果如下图所示:

image-20220701193741368.png

那类库的文档呢,继续手写 markdown?

实现了 PropsTableCodeShow 其实已经基本满足了 React 组件文档的快速编写需求。

但是业务上也有一些 Utils(工具函数) 的沉淀,如果要同时在 React 组件文档工具中编写,则需要按照原始的 markdown 写法来实现,无法直接读取注释,效率会相对低。

所以本人又开始在网上找寻了生产类库文档的解决方案,最终微软的 tsdoc 进入了我的视线,通过 tsdoc 获取注释数据,然后结合 babel-parser 解析出来的 AST 组件 props 数据,最终实现了可在 mdx 使用的 TsDoc 组件。

<TsDoc src="$utils/createFullscreen" />

效果如下图所示:

image-20220705162755873.png

image-20220705163050311.png

实现 Demo 跳转 CodeSandbox

Demo 在 CodeSandbox 中运行是锦上添花的,可有可无,也没有特别复杂。

CodeSandbox 的原理就是通过文件的文本生成 URL 字符串参数,打开 URL 后参数中的字符串会还原成文件结构和内容。

虽然是不复杂,但是还是踩了一些坑:

  • 由于 create-react-app-typescript 不支持 less module 的用法, 使用 craco 来快捷支持此功能,却发现怎么都无法支持 less module 的功能。本人猜 CodeSandbox 内部本来就做了一些模板的支持,配置 craco 无效。
  • 使用 vite 支持 less module,功能是实现了,但是打开的时候,需要运行终端安装依赖包(相对慢点),而且在线修改代码不能立即生效,刷新页面大部分情况下也会重新安装依赖包。总的来说就是运行速度相对慢。

最终还是放弃了支持 less module 的功能,采用 create-react-app-typescript 模板,然后使用原始的 css 功能实现 demo 的功能。

最终效果

直接体验可看点击这里

image-20220705170131948.png

后续的一些想法

react-doc-starter 目前基于 docusaurus 实现的文档工具适合基于第三方组件的业务组件文档,如果是像 Antd 这类自研的组件,则需要而外适配一套 UI presets 来替换 @docusaurus/preset-classic,如果有时间本人也打算实现一套 Antd 官网的主题出来。

react-doc-starter 目前 PropsTable 也只能读取默认导出的组件,其他 ts interface 的注释还不支持读取,后续可能会使用 typedoc 来实现。


Samon
1.3k 声望92 粉丝