背景
最近写了两个组件,一个是列表项高度固定的虚拟无限滚动列表,参见开发自己的第一个npm包 ;一个是九宫格跑马灯抽奖组件,参见手把手教你开发一个九宫格抽奖动画 。就想着有没有什么相对专业的技术,用来维护组件库。网上查找一番之后,这类工具还真多,一抓一大把,有vuePress/VitePress
,Docz
, gitbook
, Gatsby
, JSDoc
, TSDoc
, StoryBook
, Dumi
, MDX
, docsify
, bisheng
等等,看得人眼花缭乱,选项多了,反倒不知道怎么选了。那就快刀斩乱麻,笔者知道Vite构建速度比较快,就选VitePress
来生成组件库文档吧。
效果演示
先看看最终的效果,你也可以点击这里在线访问。组件库文档可以正常访问,站点搜索功能,也已实现。实现过程参见后面章节。
VitePress简介
VitePress发源于VuePress, 这两者的用途快速搭建静态网页项目。一般用于开发文档较多,也可以自定义主题开发 官网、博客等项目。它们的不同之处在于:
- VitePress采用Vite构建,相较于VuePress采用webpack构建,开发环境页面更新速度更快
- 采用Vue3的tree-shaking + Rollup的代码拆分,使得 VitePress 页面更轻量
- VitePress面向未来, 仅支持原生ES Module导入功能的现代浏览器
- VitePress崇尚极简主义,配置项比较少,目标是降低VuePress的复杂性
对Vite的介绍就到这里,接下来我们看看如何使用VitePress生成组件库演示文档静态站点。我们今天的目标是仿制一个和VitePress官方站点展示风格差不多的组件库文档站点。如下所示:
动手实践
步骤 1: 创建一个项目
mkdir vitepress-demo && cd vitepress-demo
步骤 2: 生成package.json文件
运行pnpn init
指令,生成项目信息:
步骤 3: 安装依赖
pnpm add vue vitepress -D
vitepress有两个peerDependencies(同伴依赖)search-insights
和@algolia/client-search
,出现警告。当你安装一个npm包时,dependencies 和 devDependencies 会被包管理器自动安装。peerDependencies 不会被自动安装。peerDependencies 一般是给插件使用的, 它的作用有以下几点:
- 要求项目拥有插件peerDependencies所指定的环境依赖
- 提升插件依赖,减少重复安装依赖
搞清楚警告的含义,运行下面的命令,手动安装一下对等依赖,消除警告。
pnpm add search-insights @algolia/client-search -D
步骤 4: 添加命令
{
...
"scripts": {
"dev": "vitepress dev 文档文件夹名称 --open --port=9000",
"build": "vitepress build 文档文件夹名称",
"preview": "vitepress serve 文档文件夹名称"
},
...
}
步骤 5: 创建文档
执行下列命令,在docs目录下创建一个空文档index.md。
mkdir docs && cd docs && touch index.md
创建完之后的项目目录如下所示:
│ .gitignore
│ package.json
│ pnpm-lock.yaml
├─.vscode
│ extensions.json
│ settings.json
├─docs
│ │ index.md
└─node_modules
VitePress工作方式是目录结构与 URL 路径相对应。会把相应的md文件转换成html文件,运行pnpm dev
, 访问 http://localhost:9000
,可以看到, 即便index.md 的内容为空,vitepress也设置了一些默认内容,如页面的title,网站的标题,黑夜/白天阅读模式等。
步骤 6: 配置文档
vitepress的配置分为三部分, 其中应用和Frontmatter配置有三项重复,其余配置项都是每种独有,每种配置项的含义请点击这里查看。
应用配置 | 主题配置 | Frontmatter配置 |
---|---|---|
appearance | logo | title |
base | siteTitle | titleTemplate |
description | nav | description |
head | sidebar | lastUpdatedlayout |
ignoreDeadLinks | outlineTitle | hero |
lang | socialLinks | features |
lastUpdated | footer | aside |
markdown | editLink | |
outDir | lastUpdatedText | |
title | carbonAds | |
titleTemplate | docFooter | |
cleanUrls(试验性的) |
步骤 7: 改造站点入口文档
我们根据实际情况,修改一下index.md的内容
---
layout: home
title: 去伪存真
titleTemplate: 组件库演示
hero:
name: 去伪存真
text: 开发的组件库
tagline: 组件库演示
image:
src: https://p3-passport.byteimg.com/img/user-avatar/df3127248f570bd043fd747ef4b00cb5~180x180.awebp
alt: 头像
actions:
- theme: brand
text: 开始
link: /guide/
- theme: alt
text: 查看源码
link: /guide/source
features:
- icon: 💡
title: 组件库技术栈
details: 基于vite4+Vue3+TypeScript开发
- icon: 📦
title: 放心使用
details: 从日常开发中提取的组件,测试充分,可投入实际项目
- icon: 🛠️
title: 实现原理分享
details: 每个组件的开发思路都分享在了掘金平台
---
再添加一下vitepress的配置文档, vitepress最重要的文档就是这个配置文档。创建好docs/.vitepress/config.ts
文件之后,输入如下内容:
import { defineConfig } from "vitepress";
export default defineConfig({
title: "去伪存真",
lastUpdated: true,
themeConfig: {
siteTitle: "组件库",
logo: "/logo.awebp",
nav: [
{ text: "思路分享", link: "/guide/thinking" },
{ text: "组件库", link: "/components/" },
{ text: "Gitee", link: "https://gitee.com/getbetter/my-comps-docs" },
{ text: "Changelog", link: "https://gitee.com/getbetter/my-comps-docs/commits/master" },
],
sidebar: {
"/components/": [
{
text: "组件库",
items: [
{ text: "九宫格抽奖", link: "/components/vue3-nine-grid-lottery" },
{ text: "虚拟滚动列表", link: "/components/vue3-virtual-list-comps" },
],
},
],
"/guide/": [
{
text: "开始",
items: [
{ text: "思路分享", link: "/guide/thinking" },
{ text: "代码仓库", link: "/guide/source" },
],
},
],
},
docFooter: { prev: "上一篇", next: "下一篇" },
footer: {
message: `去伪存真的组件库,欢迎学习交流,与点赞<a target="_blank" style="color: var(--vp-c-brand)" href="https://gitee.com/getbetter/my-comps-docs">Star ⭐</a>`,
copyright: `<a target="_blank" href="https://gitee.com/getbetter/my-comps-docs/blob/master/LICENSE">MIT License 去伪存真 </a> | 版权所有 © ${new Date().getFullYear()}`,
},
lastUpdatedText: "最后更新时间",
carbonAds: {
code: "CEBDT27Y",
placement: "vuejsorg",
},
algolia: {
appId: "", // 需要替换
apiKey: "", // 需要替换
indexName: "docs", // 需要替换
placeholder: "请输入关键词",
},
},
});
接着添加组件说明文档,添加完毕之后,项目的目录结构如下:
运行项目,可以看到index.md
和docs/.vitepress/config.ts
中配置的内容已经展示出来了,页面内容与配置文件的对应关系如下图所示:
步骤八 部署到Github Pages
登陆github, 切换到当前仓库的settings分支,设置站点访问目录为gh-pages分支的根目录(这个分支是用Github Action生成的,下文会讲),点击保存之后。接着点击Visit site按钮,就可以在线浏览静态站点。
添加文档搜索功能
需要在algolia平台注册一个账号,或者直接选择已有的github,google账号免注册登陆,获取搜索配置key。菜单路径是settings--Team and Access--API Keys。
themeConfig.algolia对象的appId和apiKey字段就来自上图。
algolia: {
appId: "", // 需要替换
apiKey: "", // 需要替换
indexName: "docs", // 需要替换
placeholder: "请输入关键词",
},
思路是,运行docker image,手动上传搜索数据到 algolia。
创建配置文件
- 创建.env环境变量文件
ALGOLIA_APP_ID=appId
ALGOLIA_API_KEY=adminKey
- 创建algolia的爬虫配置crawerConfig.json文件
vitepress-v1.0.0-beta.3版本,参照网上的老版本配置方法,会出现虽然爬虫数据上传了,在aligolia网站上调试也能搜索出来检索内容,可是在线网站却搜索不出任何内容的奇怪现象。笔者在这里踩了大坑,幸亏看到这篇文章,采用下面的配置,上传爬虫数据后才能搜索出内容。
{
"index_name": "***",
"start_urls": ["***"],
"rateLimit": 8,
"maxDepth": 10,
"selectors": {
"lvl0": {
"selector": "",
"defaultValue": "Documentation"
},
"lvl1": ".content h1",
"lvl2": ".content h2",
"lvl3": ".content h3",
"lvl4": ".content h4",
"lvl5": ".content h5",
"content": ".content p, .content li",
"lang": {
"selector": "/html/@lang",
"type": "xpath",
"global": true
}
},
"selectors_exclude": [
"aside",
".page-footer",
".next-and-prev-link",
".table-of-contents"
],
"custom_settings": {
"attributesForFaceting": ["lang", "tags"]
},
"js_render": true
}
安装jq
以管理员身份运行cmd, 先安装软件管理工具choco
@powershell -NoProfile -ExecutionPolicy unrestricted -Command "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))" && SET PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin
接着用choco安装jq
choco install jq
安装运行docker镜像
运行官方提供的 docker image 上传数据到 algolia官网。
docker run -it --env-file=.env -e "CONFIG=$(cat ./crawlerConfig.json | jq -r tostring)" algolia/docsearch-scraper
这一步在本地安装algolia/docsearch-scraper很耗时,将docker的镜像源的地址替换成阿里云镜像https://kfwkfulq.mirror.aliyuncs.com
,
能稍微快一点。
搜索功能实现改进
后面发现了更省力的方法:在github创建一个CI任务,每次提交代码时,自动运行爬虫程序,获取页面搜索数据。上面的crawlerConfig.json配置,可以复用。只需两步,便可实现此CI功能。
step1 将algolia的私钥放在github的Github Secrets
还有一个环境变量,是让GitHub的虚拟机访问GitHub仓库的,配置入口如下:
需要给这个token设置一下仓库的各种权限和token的有效期。生成之后,将token复制出来,在Github Secrets中创建一个新变量RUN_ACTIONS_TOKEN
,值为刚才生成的token值。
step2 编写CI命令
在项目根目录.github/workflows
文件夹下,创建 algolia.yml
文件, 添加如下命令,命令的含义是使用 Github Actions 在 Docker 中执行的 AlgoliaDocSearch scraper action,爬取发布网页最新内容。
yml命令是在运行器中执行的。运行器是在 GitHub Actions 工作流中执行作业的计算机。 例如,运行器可以在本地克隆存储库,安装测试软件,然后运行评估代码的命令。每个 GitHub 托管的运行器都是一个新的虚拟机 (VM),由 GitHub 托管,并且预安装了运行器应用程序和其他工具,可用于 Ubuntu Linux、Windows 或 macOS 操作系统。运行器的硬件指标如下:
Windows 和 Linux 虚拟机的硬件规格:
- 2 核 CPU (x86_64)
- 7 GB RAM
- 14 GB SSD 空间
MacOS 虚拟机的硬件规格:
- 3 核 CPU (x86_64)
- 14 GB RAM
- 14 GB SSD 空间
MacOS XL 虚拟机的硬件规格:
- 12 核 CPU (x86_64)
- 30 GB RAM
- 14 GB SSD 空间
详情参考GitHub 托管的运行器概述
name: deploy-comps-site
on:
push:
branches:
- master
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Install and Build # 下载依赖 打包项目
run: |
npm install
npm run build
- name: Deploy 🚀 # 部署
uses: JamesIves/github-pages-deploy-action@v4.3.3
with:
branch: gh-pages # 部署后提交到的分支
folder: my-comps-docs # 这里填打包好的目录名称
token: ${{ secrets.RUN_ACTIONS_TOKEN }}
algolia:
runs-on: ubuntu-latest
needs: deploy
steps:
- uses: actions/checkout@v2
- name: Get the content of algolia.json as config
id: algolia_config
run: echo "config=$(cat crawlerConfig.json | jq -r tostring)" >> $GITHUB_OUTPUT
- name: Push indices to Algolia
uses: signcl/docsearch-scraper-action@master
env:
APPLICATION_ID: ${{ secrets.ALGOLIA_APP_ID }}
API_KEY: ${{ secrets.ALGOLIA_API_KEY }}
CONFIG: ${{ steps.algolia_config.outputs.config }}
最后
以前使用代码仓库时,对readme.md文档不太重视,懒于书写。今天使用vitepress搭建组件库文档站点的过程中,发现每个项目的readme.md文件是很重要的素材。得在思想上重视起来。另外一项收获就是知道了这类网站还可以投放卡片广告,以及搜索功能需要去第三方网站注册,才能使用。本文的代码已经上传到github,你可以点此下载学习。