天天看点

Docz 组件库文档实现方案(三)Docz 组件库文档实现方案(三)

Docz 组件库文档实现方案(三)

相关

  • Docz 组件库文档实现方案 (一) Docz 使用说明及简单使用
  • Docz 组件库文档实现方案(二) 实现 Docz 定制化方案
  • Docz 组件库文档实现方案(三) Docz 与 lerna 项目的结合 – 将 docs 文档从组件库中分离出,作为一个单独的子项目维护
  • Docz 官方文档
  • Docz 官方实现案例
  • 本文的实现案例 需要进入到 packages/mjz-ui 下查看
  • 本文Lerna + Docz 实现案例(docs 与 components 分离)

Docz 结合 Lerna 项目

Docz 可以与组件库代码混合使用,即在组件实现的同级别目录创建扩展名为 mdx 的组件同名文件;

如果你的项目是 lerna 项目,那么可以尝试另外一种方案,即:将组件库组件代码与docs 文档分离成两个子项目,这样每个子项目只关心各自的实现即可,下面我们把之前的案例改造成 docs 与 components 分离,源码可以到这里查看

1. 将一个 lerna 项目改造成如下结构

其中

/packages/mjz-ui/

是组件库的实现

/packages/docz/

是组件库文档
.
├── lerna.json
├── package.json
├── packages
│   ├── docs
│   │   ├── __tests__
│   │   ├── doczrc.js
│   │   ├── gatsby-config.js
│   │   ├── package.json
│   │   ├── public
│   │   │   └── avatar.png
│   │   └── src
│   │       ├── components
│   │       ├── gatsby-theme-docz
│   │       └── index.mdx
│   └── mjz-ui
│       ├── __tests__
│       ├── package.json
│       ├── rollup.config.js
│       ├── src
│       │   ├── components
│       │   └── index.tsx
│       └── tsconfig.json
└── yarn.lock
           

2. 改造组件库,实现组件库输出组件

组件需要输出给外部 通过

import {...} from '@mjz-test/mjz-ui'

来使用,这个时候就需要给源代码编译一下了,因为我们还使用了 less 因此这个案例我们暂时使用 rollup 简单的打包一个组件库(仅测试Docz用,真正的组件库打包方案会复杂一些)
  1. 给 mjz-ui 子项目安装依赖
yarn workspace @mjz-test/mjz-ui add @rollup/plugin-commonjs @rollup/plugin-node-resolve @rollup/plugin-typescript less postcss rollup-plugin-postcss rollup react react-dom typescript
           
  1. 安装完成后给 mjz-ui 子项目 添加 script
{
  "scripts": {
    "dev": "rollup -c -w"
  },
  "dependencies": {
    "@rollup/plugin-commonjs": "^17.0.0",
    "@rollup/plugin-node-resolve": "^11.0.1",
    "@rollup/plugin-typescript": "^8.1.0",
    "less": "^4.0.0",
    "postcss": "^8.2.1",
    "react": "^17.0.1",
    "react-dom": "^17.0.1",
    "rollup": "^2.35.1",
    "rollup-plugin-postcss": "^4.0.0",
    "typescript": "^4.1.3"
  }
}
           
  1. 创建 rollup.config.js 配置文件
import typescript from '@rollup/plugin-typescript';
import postcss from 'rollup-plugin-postcss';
import commonjs from '@rollup/plugin-commonjs';
import resolve from '@rollup/plugin-node-resolve';

const config = {
  input: 'src/index.tsx',
  output: {
    dir: 'dist',
    format: 'esm',
    entryFileNames: 'index.js',
    intro: 'import "./index.css"'
  },
  plugins: [
    typescript(),
    postcss({
      extensions: ['.less', '.css'],
      extract: true,
    }),
    commonjs(),

    // 模块加载
    resolve({
      browser: true,
      jsnext: true,
      main: true,
    }),
  ],
  external: ['react', 'react-dom'],
  watch: {
    include: 'src/**'
  }
};

export default config;
           
  1. 给所有 components/ 下的组件创建一个总入口文件 /src/index.tsx
/**
 * 组件入口
 * */ 

 export {default as Alert} from './components/Alert';
 export {default as Button} from './components/Button';
           
  1. 创建 ts.config.js 配置文件, 这里就不再细说,与之前创建 ts.config.js 一致
  2. 将 /src/components/ 下组件实现与之前保持一致,但是要删除其余的 .mdx 文件
  3. 执行

    cd packages/mjz-ui && yarn dev

    即可看到编译后的组件输出到 dist/index.js 中了
  4. 将 mjz-ui/package.json 中的 module 指向这个编译后文件

    {"module": "dist/index.js"}

  5. 以上,关于组件库的改造就完成了

3. 创建一个新的 docs 子项目并实现组件库文档

可以通过

yarn lerna:create @mjz-test/docs

创建的这个组件库文档项目,创建后将其配置成如下结构
.
├── __tests__
├── doczrc.js # 从之前的 mjz-ui 迁移过来
├── gatsby-config.js # 从之前的 mjz-ui 迁移过来
├── package.json
├── tsconfig.json # 从之前的 mjz-ui 复制过来
├── public # 从之前的 mjz-ui 迁移过来
│   └── avatar.png
└── src
    ├── components # 只保留 mdx 文件
    │   ├── Alert.mdx
    │   ├── Button.less # 如果 mdx 文件中要用到样式也可以配置 gatsby-plugin-xxx 后直接引入
    │   └── Button.mdx
    ├── gatsby-theme-docz # 从之前的 mjz-ui 迁移过来 用来做文档定制化的
    │   ├── customComponents
    │   │   ├── Menu.js
    │   │   └── index.js
    │   └── index.js
    └── index.mdx
           
  1. 因为组件库文档要使用 mjz-ui 中的组件,所以我们要给 docs 这个项目引用

    @mjz-test/mjz-ui

    这个包,这个包是我们正在开大的包,所以引用时要加当前的版本号
实际上 lerna 会帮助我们把 @mjz-test/mjz-ui 这个包软连接到我们工作区的

/packages/mjz-ui

这里,每次这个包有改动也都会实时更新
  1. 组件库现在在 /packages/docs 项目中已经作为第三方 package 来使用了,因此我们需要改动对他的引用方式
# packages/docs/src/components/Alert.mdx
---
name: Alert
route: /alert
menu: Components
weight: 1
---
import { Playground, Props } from 'docz';
import {Alert, Button} from '@mjz-test/mjz-ui'; # 当做第三方包引用即可
           
除了引用方式改变外,其余与之前的使用习惯没有区别

开发时,如何用

以上就完成了 docs 与 components 的分离, 开发时
  • 先开启组件库的开发环境

    cd packages/mjz-ui && yarn dev

  • 再开启组件库文档的开发环境

    cd packages/docs && yarn dev

  • 打开 docs 的页面 http://localhost:3000 发现 Props 区块居然不见了!!
Docz 组件库文档实现方案(三)Docz 组件库文档实现方案(三)
发生如上问题的原因是,我们的组件库在编译后,输出的不再 TS 模块,虽然其 Props 等 TS 类型声明不能很好的被另一个 Docz 项目的 组件识别,因此开发环境下还是得使用未编译的组件,我们需要按照如下配置
NOTICE: 1. 为什么不将 TS module 直接导出呢?package.json 设置 main 直接导出 ts 文件是可行的,但是作为开源组件库要给更多的人使用,没有办法规定用户一定要使用 TS,因此发布前一定会编译成 JS
NOTICE: 2. 还有中方案可以考虑在TS 编译成 JS 后,将其类型改为 prop-types 定义的类型,这样就可以识别了,(虽然会增加代码体积)
// 1. 首先确保在 docs 项目下也有一个 tsconfig.json 文件其内容与 @mjz-test/mjz-ui 一致,并且将 package/mjz-ui/ 目录作为其 include 之一,来保证可以正常的编译
{ "include": ["src", "../mjz-ui/"] }

// 2. 新增 gatsby-node.js 将 @mjz-test/mjz-ui 作为 docz 运行时的 webpack alias 而这个 alias 指向的是 @mjz-test/mjz-ui 的 /src 即 ts 源码,这样 <Props> 拿到的就是 TS 组件了(而不是编译后的JS 组件) 

// packages/docs/gatsby-node.js
const path = require("path");

exports.onCreateWebpackConfig = (args) => {
  args.actions.setWebpackConfig({
    resolve: {
      alias: {
        "@mjz-test/mjz-ui": path.resolve(__dirname, "../../../packages/mjz-ui/src"),
      },
    },
  });
};

// 3. 调整 doczrc.js 配置,
{
  docgenConfig: { // 这个是一个 docz 未公开的一个配置
    searchPatterns: ["../mjz-ui/**/*"],
  },
  filterComponents: (files) =>
    files.filter((filepath) => /\/[A-Z]\w*\.(js|jsx|ts|tsx)$/.test(filepath)),
  ignore: ["README.md", "../mjz-ui/node_modules"], // 排除掉 mjz-ui 中的一些不需要的
}
           
  • 再此开启组件库文档的开发环境

    cd packages/docs && yarn dev

    发现文档可以正常编译开发了

总结

以上就完成了 docs 与 components 的分离, 开发时
  • 开启组件库文档的开发环境

    cd packages/docs && yarn dev

  • 在 packages/mjz-ui 下开发组件并调试
  • 开发完成后

    yarn lerna:publish

    mjz-ui 与 docs 会同步更新版本

继续阅读