随着工作年限的增加,越来越认同,文档是程序必不可少的一部分。话不多说,今天给大家推荐一个写文档的插件 VuePress
,它可以将你写的md
文档渲染成静态html页面,现在就可以开心地用md
文件地形式来写文档
VuePress有两种使用方式,第一种就是单独使用,第二种就是集成到项目中。我们使用第二种方式,让开发人员可以在一个地方同时进行文档编写和代码开发
首先,新建一个测试项目,新建成功
项目结构
安装VuePress
yarn add -D vuepress
创建文档根目录
已经做好了准备工作,咱们来建立目录开始写文档!在根目录添加文件夹mydocs
添加配置
VuePress的配置方式是,在当前文档目录(mydocs)下,创建一个.vuepress
文件夹,VuePress或默认去读取这个文件夹的配置下的config.js
。建立结构后:
现在我们来配置一下这个config.js
const path=require('path')
module.exports = {
title: '测试开发文档',
description: '测试开发文档',
themeConfig: {
// 侧边栏导航
sidebar: [['/', 'Start'],
['/first/', '第一个板块'],
['/second/second.md', '第二个版块']
],
sidebarDepth: 2
},
dest:path.resolve('public','mydocs'),
base:'/docs/'
}
这些配置项分别是什么意思,我就不做过多赘述,建议查阅官方文档
值得一提的是,sidebar
这个配置,代表着侧边导航栏。代码中的配置的意思是,我的文档有3个大的导航,每个数组第一个参数是要读取的路径,如果没有具体到文件名,就会默认读取该文件夹下的README.md
文件,类似于Start和第一个版块
创建文档结构
创建创建文档结构和创建配置文件没有一定的先后顺序,但是要保证两者一致
根据我们的配置文件,我们要创建对应的目录
写入运行文档脚本
好像我们的准备工作已经差不多了,怎么开始我们的文档编写呢?
和我们的代码项目类似,VuePress也是通过命令的方式启动的,在package.json
中,我们添加两个脚本
运行文档
万事具备!运行!
yarn run docs:dev
成功!让我们访问链接,在浏览器查看一下
什么都没有。。。。
当然了,你还一个字都没写呢,哈哈
修改文档
让我们往我们的md文档中写点东西!
我们把根目录的README.md
写入如下内容
## 我是首页哦
### 我是首页三级标题哦
#### 我是首页四级标题哦
其他目录下的也按照规则随意写一些,保存,查看浏览器
有啦!! 但是VuePress有个问题,不知道怎么回事,有时候导航栏不会得到刷新。我们关掉当前的线程,重新运行一下启动命令完美
如何导出文档
VuePree 执行 yarn run docs:build
命令,可以把.md文件生成静态html文件,但是当我们要把开发文档提交给领导的时候,总不能跟领导说,领导,你去访问xxxx可以看到!(大多时候,他们只信word那一套)
这里,我推荐pandoc
安装pandoc
pandoc
的作用是,把.md
文档转换成其他格式的文件
请自行搜索pandoc
,下载安装包,安装时注意勾选给所有用户使用
安装完成之后,请自行查看学习pandoc
的转换命令
现在我们可以把.md
文件转换成.docx
文件啦
但是,但是!!我们文档一旦多起来,靠手动一个命令去转换,也太蠢了吧,这不符合我用50分钟的时间写代码去完成5分钟就可以完成的事的精神,我决定写一个webpack插件,每次打包成产品的时候,就自动导出文档(打包产品的时候一般已经足够稳定)
写一个配合使用的webpack插件
直接上代码
const path = require('path')
const fs = require('fs')
const cmd = require('node-cmd')
/**
* webpack插件,当打包生产模式的时候,将vuePree的md文档输出word文档
* tx 20190705
*/
class DocsOutPutPlugin {
constructor(options) {
const defaultOptions = {
basePath: '', // 基本目录上下文
output: 'docsOutput', // 导出的目标目录
dir: 'mydocs' // 包含md文档的顶层目录
}
if (!options || !options.basePath) {
throw new Error('basePath is required')
}
this.options = Object.assign({}, defaultOptions, options)
this.outputPath = path.resolve(this.options.basePath, this.options.output)
this.docsPath = path.resolve(this.options.basePath, this.options.dir)
}
apply(compiler) {
compiler.plugin('compile', params => {
this.createDir(this.outputPath)
this.makeDocxFile(this.docsPath)
})
}
// create output dir
createDir(dir) {
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir)
}
}
// create output file
makeDocxFile(_path) {
fs.readdir(_path, (readErr, files) => {
if (readErr) {
throw readErr
}
files.forEach(file => {
const stats = fs.statSync(_path + '\\' + file)
if (stats.isFile()) {
const extname = path.extname(file).toLowerCase()
if (extname === '.md') {
const commond = `pandoc ${_path + '\\' + file} -o ${this
.outputPath +
'\\' +
file.replace('.md', '')}.docx`
cmd.run(commond)
}
} else if (stats.isDirectory()) {
const newPath = _path + '\\' + file
this.makeDocxFile(newPath)
}
})
})
}
}
module.exports = DocsOutPutPlugin
添加配置文件 webpack.pro.config.js
const DocsOutPutPlugin = require('./webpackPlugins/DocsOutPutPlugin')
module.exports = {
plugins: [new DocsOutPutPlugin({
basePath: __dirname
})]
}
修改vue.config.js
const proConfig = require('./webpack.pro.config')
module.exports = {
configureWebpack: config => {
if (process.env.NODE_ENV === 'production') {
return proConfig
}
//else {
// ERROR WebpackOptionsValidationError: Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
// return config //不太明白这里为什么会出错,结构一样,但是却报错
//}
}
}
结束!!