如何自动生成带示例的vue文档

4,612 阅读3分钟

开发工程师最不想做的事情是什么?

写注释写文档

而最不希望别人不做的事情是什么?

别人不写注释和文档

为什么产生文档生成的想法

由于需要接手一个没有文档的项目, 其中包含一个自定义的 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

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

NameDescriptionTypeRequiredDefault
sizemedium / small / miniStringfalsemedium
typeprimary / success / warning / danger / info / textStringfalse-

Slots

NameDescriptionDefault 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.xreact需要怎么处理呢?

    • 解决方案 : vue 语法树的解析并不是从零开始,最好的解析工具淡然就是官网 vue 里面的解析器. 所以 vue2 也好 vue3 也罢. 只需要将工具链上的工具替换成对应的版本(肯定需要兼容处理),就能自动生成文档,毕竟思路是相通的. react 不也一样吗?
  • 咳咳 gulpfile.js 的代码实在是让我自己汗颜,无颜见江东父老. 还需好好磨练

  • 文档效果一般,在功能上也可以提供像 element-ui 类似的文档,如果是在小公司内部使用的话,想来还是不错的解决方案的.

github 项目地址

github 完整示例