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用,真正的组件库打包方案会复杂一些)
- 给 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
- 安装完成后给 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"
}
}
- 创建 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;
- 给所有 components/ 下的组件创建一个总入口文件 /src/index.tsx
/**
* 组件入口
* */
export {default as Alert} from './components/Alert';
export {default as Button} from './components/Button';
- 创建 ts.config.js 配置文件, 这里就不再细说,与之前创建 ts.config.js 一致
- 将 /src/components/ 下组件实现与之前保持一致,但是要删除其余的 .mdx 文件
- 执行
即可看到编译后的组件输出到 dist/index.js 中了cd packages/mjz-ui && yarn dev
- 将 mjz-ui/package.json 中的 module 指向这个编译后文件
{"module": "dist/index.js"}
- 以上,关于组件库的改造就完成了
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
- 因为组件库文档要使用 mjz-ui 中的组件,所以我们要给 docs 这个项目引用
这个包,这个包是我们正在开大的包,所以引用时要加当前的版本号
@mjz-test/mjz-ui
实际上 lerna 会帮助我们把 @mjz-test/mjz-ui 这个包软连接到我们工作区的 /packages/mjz-ui
这里,每次这个包有改动也都会实时更新
- 组件库现在在 /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 区块居然不见了!!
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL6tGVPh3YtJGao1WZxFjMMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL4cTOyMjMyYTM0ATMwEjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
发生如上问题的原因是,我们的组件库在编译后,输出的不再 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 下开发组件并调试
- 开发完成后
mjz-ui 与 docs 会同步更新版本yarn lerna:publish