前言
本期devui团队的核心成员wailen也加入进来和kagol一起分享组件库文档建设的经验,衷心感谢他们的无私分享!
视频教程
上一期内容回顾
上一期给大家分享了如何使用vite搭建一个支持ts/jsx的vue3组件库工程,并接上了咱们第一次直播编写的jsx风格的tree组件,内容不多,算是咱们组件库工程化的一个开场。
有了基础工程,就可以往里面不断丰富组件啦,这时我们会发现一个问题,写好的组件,在哪里看效果呢?
我们还缺少一个展示组件demo/api的文档系统,这个文档系统至少需要有以下模块/功能:
- 需要一个左侧菜单,用来展示我们有哪些组件
- 点击左侧菜单中的组件,可以展示这个组件的基本信息、Demo、API文档
技术选型
由于我们使用的是Vite构建工具,因此需要选择一款与其配套的文档系统。
当从vue的生态上来说,需要决策的是选择VuePress还是VitePress,最终我们选择VitePress,主要原因是:
- VitePress是基于Vite的,而VuePress是基于Webpack的(也可以通过配置
改成Vite构建)bundler: '@vuepress/bundler-vite'
- VitePress更快更轻量,极易上手
参考:
https://v2.vuepress.vuejs.org/zh/guide/#%E4%B8%BA%E4%BB%80%E4%B9%88%E4%B8%8D%E6%98%AF
添加VitePress文档
安装vitepress:
yarn add -D vitepress
创建第一个文档:
mkdir docs && echo '# Hello VitePress' > docs/index.md
增加脚本命令:
{
"scripts": {
"docs:dev": "vitepress dev docs",
"docs:build": "vitepress build docs",
"docs:serve": "vitepress serve docs"
}
}
本地启动:
yarn docs:dev
浏览器访问看效果:
http://localhost:3000/
这是VitePress默认的效果。
参考:
https://vitepress.vuejs.org/guide/getting-started.html
配置VitePress
我们需要实现以下功能:
- 需要一个左侧菜单,用来展示我们有哪些组件
- 点击左侧菜单中的组件,可以展示这个组件的基本信息、Demo、API文档
配置sidebar
VitePress有一个配置文件,里面有一个themeConfig/sidebar配置,可以配置左侧菜单。
docs/.vitepress/config.ts
const sidebar = {
'/': [
{ text: '快速开始', link: '/' },
{
text: '通用',
children: [
{ text: 'Button 按钮', link: '/components/button/' },
]
},
{
text: '导航',
},
{
text: '反馈',
},
{
text: '数据录入',
},
{
text: '数据展示',
},
{
text: '布局',
},
]
}
const config = {
themeConfig: {
sidebar,
}
}
export default config
点击左侧菜单的Button,看下效果:
http://localhost:3000/components/button/
页面404了
img
创建Button组件的文档
404的原因是我们没有创建相应的文档
docs/component/button/index.md
先随便写一些内容
# Button 按钮
在看下效果:
img
在md中增加vue组件
VitePress的一大好处是可以直接在md中写vue组件,VitePress会将其渲染出来。
docs/components/button/index.md
# Button 按钮
<d-button></d-button>
img
编写一个Button组件
devui/button/src/button.tsx
const Button = () <div>Button 按钮</div>
export default Button
引入Button组件
docs/.vitepress/theme/index.ts
import Theme from 'vitepress/dist/client/theme-default'import Button from '../../../devui/button/src/button'export default { ...Theme, enhanceApp({ app }) { app.component('d-button', Button) }}
报错:React is not defined
这个报错是不是非常熟悉?没错!上一次直播我们也遇到过,相信聪明的你一定知道是怎么回事,也知道怎么解决啦~
Uncaught (in promise) ReferenceError: React is not defined at Button (button.tsx:1)
引入jsx插件
安装jsx插件:
yarn add -D @vitejs/plugin-vue-jsx
docs/vite.config.ts
中引入jsx插件:
import { defineConfig } from 'vite'import vueJsx from '@vitejs/plugin-vue-jsx'// https://vitejs.dev/config/export default defineConfig({ plugins: [vueJsx()]})
组件显示出来了!
img
demo代码展开/收起
这部分内容由wailen同学分享。
引入背景
早期进行组件开发的时候,demo展示部分需要用`````包裹展示的代码块,另外组件的显示也需要同样的代码,所以同样的代码写了两遍,非常的不“银杏”。比如下面这样
<!-- index.md --> <!-- 以下是显示组件部分 --> <d-icon name="emoji"><d-icon> <d-icon name="emoji" color="#3dcca6"><d-icon> <!-- 以下是暴露到文档的代码块 --> <!-- 需要再次重复写同样的代码 --> ```html <d-icon name="emoji"><d-icon> <d-icon name="emoji" color="#3dcca6"><d-icon> ```
所以在网上看看有没有现成的方案了,
毕竟
img
但是
vitepress
和
vue3
当时解决方案还不太多,所以也不抱太多希望。
不过最终很幸运的发现了两款支持vitepress的demo展示插件
vitepress-theme-demoblock
和
vitepress-for-component
。但最后调研发现
vitepress-for-component
是 fork 自
vitepress
的脚手架,并不单单是一个插件了,不好集成到devui中,最后就确定了
vitepress-theme-demoblock
。
插件的使用
安装
npm install -D vitepress-theme-demoblockyarn add -D vitepress-theme-demoblock
注入插件
首先我们得知道
vitepress
关于
markdown
的拓展规则,vitepress 使用
markdown-it
作为 markdown 渲染器,具体可以查看
我们得将插件在
vitepress
的
config.js
中注册,如下面这样:
module.exports = { markdown: { config: (md) => { // 这里可以使用 markdown-it 插件,vitepress-theme-demoblock就是基于此开发的 const { demoBlockPlugin } = require('vitepress-theme-demoblock') md.use(demoBlockPlugin) } }}
demoBlockPlugin插件的核心
demoBlockPlugin
是插件的核心方法,函数内部注册了三个方法,如下:
// vitepress-theme-demoblock/demoblock/index.jsconst demoBlockPlugin = (md, options = {}) => { md.use(blockPlugin, options) md.use(codePlugin, options) md.use(renderPlugin, options)}
- blockPlugin:
的作用是根据blockPlugin
插件获取到的md文档所有内容转换成的AST树,从树中获取到被语法markdown-it-container
包裹的部分,输出成大概如下的字符串格式。:::demo
// content就是需要渲染组件的代码内容`<demo sourceCode="${content}"> <!--vue-demo:${content}:vue-demo--></demo>`
- codePlugin:
作用是生成描述部分codePlugin
和代码展示部分description
,使用了vue的具名插槽渲染。其中highlight
可以满足md语法。比如下面这样使用。description
:::demo 使用`size`、`style`属性来定义 Card 的样式。 ```vue <template> <div class="card-wrap"> <div class="card">{{ title }}</div> </div> </template> ```:::
最终生成的效果如图所示
img
红色部分就是
description
,黑色部分对应
highlight
- renderPlugin:顾名思义渲染函数,将上面
函数返回的blockPlugin
部分,通过正则表达式的形式获取到需要输出的<!--vue-demo:${content}:vue-demo-->
内容,最终渲染出来。template, script, style
devui
将所有
docs/.vitepress/config.js
中的配置项都单独抽离了逻辑,在阅读项目源码的时候需要注意下。
注入主题与插件的组件
vitepress的主题拓展可以查看
我们得在
docs/.vitepress/theme/index.ts
中注册
vitepress-theme-demoblock
插件的
demo
组件,如下面这样
// 主题样式import 'vitepress-theme-demoblock/theme/styles/index.css'// 插件的组件,主要是demo组件import { registerComponents } from './register-components.js'export default { enhanceApp({ app }) { registerComponents(app) }}
那么上面引入的
register-components.js
怎么来的呢?这个文件其实不需要我们创建,可以使用脚本自动创建该文件,这样的好处是所有需要的插件组件都不需要我们手动进行注册,全部在插件内部就能确定,未来插件有任何改动都不需要修改这里。该文件长这样
// register-components.js
import Demo from 'vitepress-theme-demoblock/components/Demo.vue'
import DemoBlock from 'vitepress-theme-demoblock/components/DemoBlock.vue'
export function registerComponents(app) {
app.component('Demo', Demo)
app.component('DemoBlock', DemoBlock)
}
自动生成该文件可以使用如下命令
// package.json
"scripts": {
"register:components": "vitepress-rc"
}
yarn register:components
至此,
vitepress-theme-demoblock
的就在vitepress中注册成功了
使用与效果
注册好插件过后,我们只需要在demo展示文件
index.md
中使用固定语法包裹代码就能自动生成组件demo以及代码块
:::demo 使用`sm`,`''`,`lg`来定义`Search`基本类型
```vue
<template>
<div>
Small
<d-search size="sm" autoFocus style="width: 200px" :delay="1000"></d-search>
Middle
<d-search style="width: 200px" isKeyupSearch></d-search>
Large
<d-search iconPosition="left" size="lg" style="width: 200px"></d-search>
Disabled
<d-search disabled style="width: 200px"></d-search>
</div>
</template>
```
:::
生成的效果如下
img
效果非常棒~
遇到的问题
开源库的协议
在提议使用了
vitepress-theme-demoblock
后,有一天
Kagol
找到了我
img
李姐李姐,毕竟得保护知识产权嘛。于是乎,我就去插件库看了一下,在此之前,我一直认为的开源协议是这样的:
// package.json
{
"name": "vue-devui",
"version": "0.0.1",
"license": "MIT",
"dependencies": {},
}
嗯,源码中的
package.json
有个
license
为
MIT
,ok,fine。于是乎我立马回复大佬
img
于是便安安心心的学习去了。
结果突然有一天,Kagol又找到了我,告诉我插件没有开源协议,并告诉我开源协议要是这样的
img
定了定神,于是乎,又去了解了开源协议,原来开源库必须得定义好
LICENSE
文件,原来协议分好几种:
-
: 最为宽松的协议,意味着对所有人免费,并且可以任意处置,包括使用,复制,修改,合并,发表,分发,再授权,或者销售。唯一的限制是,软件中必须包含上述版权和许可提示MIT
-
: 需要包含一份版权提示和免责声明之外,没有任何限制BSD
-
: 保证了所有开发者的权利,同时为使用者提供了足够的复制,分发,修改的权利,可自由复制,可自由分发,可用来盈利,可自由修改GNU GPL
-
: 对产品所保留的权利比 GPL 少,因为 GPL 要求,使用了 GPL 代码的产品必须也使用 GPL 协议,开发者不允许将 GPL 代码用于商业产品。LGPL 绕过了这一限制GNU LGPL
-
: 除了为用户提供版权许可之外,还有专利许可,对于那些涉及专利内容的开发者而言,该协议最适合Apache
devui就是使用了MIT协议,所以我们可以放心大胆的使用,当然,
vitepress-theme-demoblock
也在跟开发作者邮件沟通过后,补加上了MIT协议。小伙伴们平时在使用第三方库的时候也需要注意下是否有开源协议哦。
插件的bug
最开始使用
vitepress-theme-demoblock
时,还是会碰到一些坑,比如下面这样
img