开发工程师最不想做的事情是什么?
写注释
和写文档
。
而最不希望别人不做的事情是什么?
别人不写注释和文档
为什么产生文档生成的想法
由于需要接手一个没有文档的项目, 其中包含一个自定义的 UI
库,问题来了,没有文档怎么解决。
想了半天,当然是需要补充文档,既然要补充文档,那么可不可以自动生成文档,自动生成文档那么能不能生成带示例的文档呢? 要知道对于前端来说,一个自定义的 UI
库,没有示例只看属性,如同天书呀!
开始寻找合适的方案
经过几个小时的检索,终于找到了一个合适的方案生成文档。
答案那就是 vuese
,一个基于 vue
语法解析的自动文档生成工具
深入思考解决方案
这个方案是为 vue
定制的,思路很简单,但是也非常棒
vuese
解析**.vue
文件生成Markdown
文件docute
解析**.md
文件生成HTML
文件- 将
HTML
部署为在线文档
看上去自动文档生成就一气呵成了.
等等,UI
库如果全部都是干巴巴的文字,想来谁也很难明白这个组件的实际效果如何,毕竟眼见为实,如果能够提供组件示例和代码示例,对于新人来说,会被感动的痛哭流涕吧 (不行了,不能继续YY了,说干就干,寻找方案)
再通过一顿捣鼓, 发现 docute
本身是使用 vue
开发的,docute
也支持用户扩展,支持使用vue
自定义组件,那么把组件库构建一个 umd
引入页面,然后直接使用代码示例引用vue
不是就万事大吉吗?
开始动手生成文档
先创建一个 ui 库
由于创建库过程繁琐,不再赘述。末尾会提供完整的项目示例
先假设目录结构如下
root
├── src
├──├── lib
├──├──├── Button.vue
编写 Button 组件
<template>
<button @click="btnClick">
<!-- 这里是模认插槽啦 -->
<slot></slot>
</button>
</template>
<script>
export default {
name:'DemoButton',
props:{
// `medium` / `small` / `mini`
size:{
type:String,
default:'medium'
},
// primary / success / warning / danger / info / text
type:{
type:String,
defaut:'primary'
}
},
methods:{
btnClick(){
// 这是点击事件
this.$emit('click')
}
}
}
</script>
<style scoped>
button{
background-color: #4CAF50; /* Green */
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
}
</style>
全局安装 vuese
npm i -g @vuese/cli
在项目下执行
vuese gen #创建一个 website 目录,并生成文档
现在目录结构如下
root
├── src
├──├── lib
├──├──├── Button.vue
├── website
├──├── index.html
├──├── components
├──├──├── DemoButton.md
vuese serve --open #启动服务并自动在浏览器打开
此时你能够在浏览器查看到如下页面
DemoButton
Props
Name | Description | Type | Required | Default |
---|---|---|---|---|
size | medium / small / mini | String | false | medium |
type | primary / success / warning / danger / info / text | String | false | - |
Slots
Name | Description | Default Slot Content |
---|---|---|
default | 这里是模认插槽啦 | - |
不得不说, vuese
配合注释自动生成的文档其实还是相当不错的。
给文档添加示例
先给自动生成的 website/index.html
引入创建的library
很显然在 button.vue
的代码中添加示例不是一件好的事情,那么单独建一个文件写示例代码,最后合并到 vuese
生成的 Markdown
不就可以吗?
在 lib 下创建一个新文件 DemoButton.md
root
├── src
├──├── lib
├──├──├── Button.vue
├──├──├── DemoButton.md
├── website
├──├── index.html
├──├── components
├──├──├── DemoButton.md
DemoButton.md 的内容如下
<template>
<DemoButton @click="btnClick">{{btn}}</DemoButton>
</template>
# docute 可以 mixins vue的代码,相当于 import 下面这段代码并混入,并不会被展示
```js {mixin:true}
{
data() {
return {
btn: 'btn-text'
}
},
methods:{
btnClick(){
alert('click me')
}
}
}
```
# 用来作为 markdown 代码的示例部分
```html
<template>
<DemoButton @click="btnClick">{{btn}}</DemoButton>
</template>
<script>
export default {
data() {
return {
btn: 'btn-text'
}
},
methods:{
btnClick(){
alert('click me')
}
}
}
</script>
```
好了开始合并文档,合并文档话,是使用了 gulp
来执行的.
在项目目录下添加 gulpfile.js
root
├── src
├──├── lib
├──├──├── Button.vue
├──├──├── DemoButton.md
├── website
├──├── index.html
├──├── components
├──├──├── DemoButton.md
├── gulpfile.js
gulpfile.js 文件内容如下,有些小乱,嘻嘻 ^_^
const { src, dest, series } = require('gulp')
const fs = require('fs')
const through2 = require('through2');
// 迭代 lib 下的所有 md 文件,并合并到 website/components 下的同名文件,所以文件名别乱取,自然 可以采用个人喜欢的任何策略去合并
function generateMd(){
return src('./src/lib/**/*.md').pipe(through2.obj(function (file, _, cb) {
let filename = file.path.split('\\').pop()
if (file.isBuffer()) {
try{
fs.readFile(`./website/components/${filename}`, (err, data) => {
if (err) throw err;
let fileContent = file.contents.toString() + '\n\n' + data
fs.writeFile(`./website/components/${filename}`, fileContent , (err)=>{
if(err)return console.error(err)
console.log(`写入 ${filename} 成功`)
cb()
})
});
}catch(exception){
cb()
}
}
}))
}
// 将编译好的 umd 复制到 website 目录,index.html 是引入 umd 之后的文件,其他和 vuese 自动生成的内容没有区别
function copyFile(){
return src(['./dist/*.js','./dist/*.css','./document/index.html']).pipe(dest('./website/'))
}
exports.default = series(generateMd,copyFile)
现在配置一下package.json
命令,好自动化
在script
属性下添加
"document" : "npm run build && vuese gen && gulp && vuese serve --open"
- npm run build 构建 library
- vuese gen vuese自动生成文档
- gulp 将我们写的示例合并到自动生成的文档中
- vuese serve 启动服务
接下来我们看到的示例如下
至此一个可以添加示例的自动化文档生成内容就已经完成了
总结优化和扩展
-
问题1 : 在生成示例时,很显然混入的部分,和纯粹展示的部分重叠了
- 解决方案: 这里可以再解析一次 Markdown文档,只编写示例,展示的代码,通过解析示例自动生成
-
问题2 : 由于文档生成是基于
vue2.x
的那么vue3.x
、react
需要怎么处理呢?- 解决方案 : vue 语法树的解析并不是从零开始,最好的解析工具淡然就是官网 vue 里面的解析器. 所以 vue2 也好 vue3 也罢. 只需要将工具链上的工具替换成对应的版本(肯定需要兼容处理),就能自动生成文档,毕竟思路是相通的. react 不也一样吗?
-
咳咳 gulpfile.js 的代码实在是让我自己汗颜,无颜见江东父老. 还需好好磨练
-
文档效果一般,在功能上也可以提供像 element-ui 类似的文档,如果是在小公司内部使用的话,想来还是不错的解决方案的.