捣鼓一下组件库演示文档

1,720 阅读7分钟

背景

最近写了两个组件,一个是列表项高度固定的虚拟无限滚动列表,参见开发自己的第一个npm包 ;一个是九宫格跑马灯抽奖组件,参见手把手教你开发一个九宫格抽奖动画 。就想着有没有什么相对专业的技术,用来维护组件库。网上查找一番之后,这类工具还真多,一抓一大把,有vuePress/VitePress,Docz, gitbook, Gatsby, JSDoc, TSDoc, StoryBook, Dumi, MDX, docsify, bisheng 等等,看得人眼花缭乱,选项多了,反倒不知道怎么选了。那就快刀斩乱麻,笔者知道Vite构建速度比较快,就选VitePress来生成组件库文档吧。

效果演示

先看看最终的效果,你也可以点击这里在线访问。组件库文档可以正常访问,站点搜索功能,也已实现。实现过程参见后面章节。

channel.gif

VitePress简介

VitePress发源于VuePress, 这两者的用途快速搭建静态网页项目。一般用于开发文档较多,也可以自定义主题开发 官网、博客等项目。它们的不同之处在于:

  • VitePress采用Vite构建,相较于VuePress采用webpack构建,开发环境页面更新速度更快
  • 采用Vue3的tree-shaking + Rollup的代码拆分,使得 VitePress 页面更轻量
  • VitePress面向未来, 仅支持原生ES Module导入功能的现代浏览器
  • VitePress崇尚极简主义,配置项比较少,目标是降低VuePress的复杂性

对Vite的介绍就到这里,接下来我们看看如何使用VitePress生成组件库演示文档静态站点。我们今天的目标是仿制一个和VitePress官方站点展示风格差不多的组件库文档站点。如下所示:

image.png

动手实践

步骤 1: 创建一个项目

mkdir vitepress-demo && cd vitepress-demo

步骤 2: 生成package.json文件

运行pnpn init指令,生成项目信息:

image.png

步骤 3: 安装依赖

pnpm add vue vitepress  -D

image.png

vitepress有两个peerDependencies(同伴依赖)search-insights@algolia/client-search,出现警告。当你安装一个npm包时,dependencies 和 devDependencies 会被包管理器自动安装。peerDependencies 不会被自动安装。peerDependencies 一般是给插件使用的, 它的作用有以下几点:

  1. 要求项目拥有插件peerDependencies所指定的环境依赖
  2. 提升插件依赖,减少重复安装依赖

搞清楚警告的含义,运行下面的命令,手动安装一下对等依赖,消除警告。

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,网站的标题,黑夜/白天阅读模式等。

image.png

步骤 6: 配置文档

vitepress的配置分为三部分, 其中应用和Frontmatter配置有三项重复,其余配置项都是每种独有,每种配置项的含义请点击这里查看。

应用配置主题配置Frontmatter配置
appearancelogotitle
basesiteTitletitleTemplate
descriptionnavdescription
headsidebarlastUpdatedlayout
ignoreDeadLinksoutlineTitlehero
langsocialLinksfeatures
lastUpdatedfooteraside
markdowneditLink
outDirlastUpdatedText
titlecarbonAds
titleTemplatedocFooter
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: "请输入关键词",
    },
  },
});

接着添加组件说明文档,添加完毕之后,项目的目录结构如下:

image.png

运行项目,可以看到index.mddocs/.vitepress/config.ts中配置的内容已经展示出来了,页面内容与配置文件的对应关系如下图所示:

d995bc4c2de383020aab71145bcef05.png

image.png

步骤八 部署到Github Pages

登陆github, 切换到当前仓库的settings分支,设置站点访问目录为gh-pages分支的根目录(这个分支是用Github Action生成的,下文会讲),点击保存之后。接着点击Visit site按钮,就可以在线浏览静态站点。

image.png

添加文档搜索功能

需要在algolia平台注册一个账号,或者直接选择已有的github,google账号免注册登陆,获取搜索配置key。菜单路径是settings--Team and Access--API Keys。

image.png

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, 能稍微快一点。

image.png

搜索功能实现改进

后面发现了更省力的方法:在github创建一个CI任务,每次提交代码时,自动运行爬虫程序,获取页面搜索数据。上面的crawlerConfig.json配置,可以复用。只需两步,便可实现此CI功能。

step1 将algolia的私钥放在github的Github Secrets

image.png

还有一个环境变量,是让GitHub的虚拟机访问GitHub仓库的,配置入口如下: 需要给这个token设置一下仓库的各种权限和token的有效期。生成之后,将token复制出来,在Github Secrets中创建一个新变量RUN_ACTIONS_TOKEN,值为刚才生成的token值。

image.png

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,你可以点此下载学习。