跳到主内容

从零搭建生产可用的 VitePress 文档站:从初始化、内容增强到构建部署全链路实战 ​

团队文档散落在各种聊天记录和网盘里,新人上手要翻三天聊天记录;个人知识库用笔记软件写,换个设备同步一团乱麻。这两个痛点的共同解法是把文档做成站点:内容用 Markdown 版本化管理,构建成静态页面全文可搜、随处可访。VitePress 凭借 Vite 的秒级冷启动和极小的构建产物,是当前搭建文档站性价比最高的方案之一。本文带你从零跑通一个可用于生产的 VitePress 站点。

在正式动手前,先横向对比一下主流静态文档方案,帮助你确认技术选型:VuePress 生态成熟但基于 Webpack,冷启动通常在数秒到十几秒,产物中 Vue 运行时占比较高;Docusaurus 由 Meta 维护,React 技术栈友好,但默认包体更大、配置项更重;Docsify 运行时解析 Markdown,首屏依赖 JS 执行,SEO 与首屏性能天然吃亏;VitePress 基于 Vite + Vue 3,开发服务器冷启动普遍在几百毫秒级,生产页面对每个页面做代码分割,首屏 CSS/JS 通常可控制在数十 KB 量级(gzip 后)。对于以 Markdown 为主、希望「写完即上线」的团队知识库,VitePress 是投入产出比最高的选择。

十分钟初始化一个可用的站点 ​

VitePress 的初始化成本极低,三条命令即可跑起来:

bash
npm init -y
npm add -D vitepress
npx vitepress init   # 交互式生成基础骨架

执行 npx vitepress init 时,向导会依次询问站点标题、描述、主题(默认/可爱)、是否使用 TypeScript、是否启用本地搜索等,新手一路回车即可得到可运行骨架。建议在 package.json 中补齐标准脚本,避免团队成员记忆命令:

json
{
  "scripts": {
    "docs:dev": "vitepress dev docs",
    "docs:build": "vitepress build docs",
    "docs:preview": "vitepress preview docs"
  }
}

初始化后核心目录只有三处:docs/.vitepress/config.mts 是站点配置中枢,docs/index.md 是首页,其余 Markdown 文件即页面。VitePress 的哲学是「约定优于配置」:目录结构即 URL 结构,docs/guide/getting-started.md 自动对应 /guide/getting-started.html,不需要手动注册路由。以目录 /guide/ 结尾的文件会优先解析为该目录下的 index.md,这对组织章节首页非常友好。

第一个值得认真写的配置是导航与侧边栏:

typescript
// docs/.vitepress/config.mts
import { defineConfig } from 'vitepress'

export default defineConfig({
  lang: 'zh-CN',
  title: '团队知识库',
  description: '团队内部技术文档与研发规范',
  lastUpdated: true,
  cleanUrls: true,
  themeConfig: {
    nav: [{ text: '指南', link: '/guide/' }],
    sidebar: {
      '/guide/': [
        {
          text: '入门',
          collapsed: false,
          items: [
            { text: '快速开始', link: '/guide/getting-started' },
            { text: '写作规范', link: '/guide/writing-style' }
          ]
        }
      ]
    },
    outline: {
      level: [2, 3],
      label: '本页目录'
    },
    docFooter: {
      prev: '上一页',
      next: '下一页'
    },
    lastUpdatedText: '最后更新'
  }
})

侧边栏按路径前缀分组('/guide/' 是一组、'/api/' 是另一组),这个「前缀即分组」的设计让多模块站点无需任何插件就能井井有条。需要注意前缀匹配是「最长前缀优先」,因此 /guide/advanced/ 可以单独定义更细的侧边栏,而不会被 /guide/ 覆盖。

避坑清单:其一,link 必须以 / 开头且省略 .md 后缀,写错大小写在大小写敏感的 Linux 构建机上会直接死链;其二,nav/sidebar 配置会随文档增长变得很长,建议拆成 nav.ts、sidebar.ts 再在 config.mts 中合并;其三,base 字段只有部署在子路径(如 GitHub Pages 的 https://user.github.io/repo/)时才需要设置为 /repo/,部署在域名根路径时务必留空,否则所有静态资源都会 404。

内容能力:代码高亮、容器与全文搜索 ​

技术文档站的生命线是代码块体验。VitePress 基于 Shiki 做语法高亮,它采用与 VS Code 同源的 TextMate 语法与主题,颜色还原度远高于传统的 Prism.js,并且在构建期完成高亮,运行时零 JS 开销。它支持行高亮与差异对比,写教程时直接标出「改哪行」:

markdown
```ts:line-numbers {3}
function calcPrice(price: number) {
  // 折扣逻辑
  return price * 0.9
}
```

```ts
export function add(a: number, b: number) {
  return a + b
  // 差异对比:下面这行是新增
  return a + b 
  // 这行是删除
  return a - b 
  // 聚焦某一行,其余行变暗
  return a + b 
}
```

其中 :line-numbers 开启行号,{3} 表示高亮第 3 行,也支持区间写法 {2-5} 与多段写法 {2,4-6};// [!code ++]、// [!code --]、// [!code focus] 是行内指令,非常适合在评审文档中讲解 diff。

配合 ::: tip / ::: warning / ::: danger 容器语法,可以做出醒目的注意事项块,还可以通过 ::: info 自定义标题 指定标题,甚至嵌套容器:

markdown
::: tip 性能提示
生产环境请开启 gzip 或 brotli 压缩,文本类资源体积通常可再降 70% 以上。
:::

::: warning
不要把密钥、内网地址写进 Markdown,静态站点对全网可见。
:::

::: details 点击查看完整配置
```ts
export default { /* ... */ }

:::


搜索方面,VitePress 内置了基于 Mini Search 的本地全文搜索,零外部依赖、无隐私顾虑,中小型站点直接开启即可:

```typescript
themeConfig: {
  search: {
    provider: 'local',
    options: {
      translations: { search: { placeholder: '搜索文档…' } },
      // 忽略生成目录与第三方文档,控制索引体积
      exclude: (path) => path.includes('changelog'),
      // 只索引正文与标题,提升相关性
      detailedView: true
    }
  }
}

本地搜索的原理是构建时把所有 Markdown 抽成倒排索引,随首屏以 JSON 形式按需加载。实测一个约 300 页、正文 15 万字的内部知识库,索引文件 gzip 后约 600KB,首次搜索延迟在 100ms 以内,完全可接受。文档量超过几千页或需要更高召回质量(拼音、同义词、跨语言)时,再考虑接入 Algolia DocSearch(开源项目可免费申请)或基于 Meilisearch/Typesense 自建索引。

避坑清单:本地搜索默认不索引代码块内容,若希望 API 名能被搜到,需要在正文中以普通文本重复一次关键标识;中文分词依赖浏览器内置的 Unicode 切分,对长句召回不如专业分词器,关键词尽量在标题中出现;切换搜索 provider 后必须重启 dev server,热更新不会重建索引。

构建优化:让站点又小又快 ​

VitePress 默认产物已经很小,但仍有三个立竿见影的优化点。第一,死链检查前置:vitepress build 默认校验内部死链,把 cleanUrls: true 开启后 URL 去掉 .html 后缀更简洁,构建期的死链报错能拦住绝大多数文档失修问题。如果 CI 中希望对死链零容忍,可加上 --strict 语义:在脚本中使用 "docs:build": "vitepress build docs --strict"(部分版本通过环境变量或 CI 退出码控制,升级前请核对当前版本文档),任何死链、失效 frontmatter 引用都会让构建以非零码退出。

第二,图片统一放 public 目录,用根路径 /images/xxx.png 引用,构建时按需拷贝不参与打包,大图建议外链对象存储并加宽高占位防布局抖动。更推荐的做法是把截图统一压缩为 WebP/AVIF:实测一张 1920px 宽的 PNG 截图从 2.1MB 压到 WebP 后约 180KB,体积下降约 91%,肉眼几乎无差异。在 Markdown 中可以这样写以避免 CLS(累积布局偏移):

markdown
<img src="/images/arch.png" width="1200" height="640" alt="系统架构图" loading="lazy" decoding="async" />

第三,合理使用动态路由与懒加载,大块代码示例拆成独立 md 用 VitePress 的代码块引入语法复用,避免单页无限膨胀。VitePress 支持在 Markdown 中直接引入文件作为代码块:

markdown
```ts
//<<< @/../src/utils/price.ts#snippet
```

配合源文件中的 // #region snippet 与 // #endregion 标记,即可只引入指定片段,文档代码永远与仓库真实代码一致,从根本上杜绝「文档里的示例已经跑不通」。对于超大页面,还可以利用 Vue 组件能力做异步渲染:

vue
<script setup>
import { defineAsyncComponent } from 'vue'
const HeavyDemo = defineAsyncComponent(() => import('../components/HeavyDemo.vue'))
</script>

<HeavyDemo />

部署上静态产物 docs/.vitepress/dist 可以扔到任何静态托管平台。国内环境推荐对象存储 + CDN,配合 CI 在文档仓库 push 时自动构建部署,整个链路零服务器运维成本。下面是一份可直接使用的 GitHub Actions 示例(部署到任意支持静态文件的平台,产物通过 actions/upload-pages-artifact 或同步到 OSS):

yaml
name: deploy-docs
on:
  push:
    branches: [main]
permissions:
  contents: read
  pages: write
  id-token: write
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: npm
      - run: npm ci
      - run: npm run docs:build
      - uses: actions/upload-pages-artifact@v3
        with:
          path: docs/.vitepress/dist
  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - id: deployment
        uses: actions/deploy-pages@v4

实战经验:务必给 CDN 配置正确的缓存策略——带哈希的静态资源(/assets/*.js、*.css)可以 cache-control: public, max-age=31536000, immutable,而 HTML 与 searchIndex.json 建议走短缓存或协商缓存,否则文档更新后用户可能长时间拿到旧页面。量化参考:一个 200 页左右的文档站,冷构建通常在 20~40 秒,热重建(仅改动一个 md)在 500ms 以内;gzip 后单页首屏传输量普遍低于 80KB,在 4G 网络下 LCP 可控制在 1.5 秒上下。

实践清单 ​

  1. 目录结构即信息架构,动手写文档前先设计好目录树。
  2. 侧边栏按路径前缀分组,每个模块独立管理导航。
  3. 本地搜索先行,文档量上来后再升级外部搜索服务。
  4. 构建期死链检查保持开启,文档失修在 CI 阶段暴露。
  5. 图片走 public 目录与 CDN,代码示例拆分复用控制单页体积。

在此基础上再补充几条来自生产环境的经验:一是把「文档评审」并入代码 PR 模板,改动接口必须在同一 PR 中更新对应 md,否则不予合并;二是为高频文档建立 CODEOWNERS,由模块负责人把关准确性;三是定期(如每季度)用脚本扫描「超过 180 天未更新且引用了版本号」的页面,自动提 issue 提醒复核;四是善用 frontmatter 的 title、description、sidebar: false、aside: false 等能力,为 landing page 或全屏 Demo 关闭默认布局;五是建立统一的「术语表」与「写作规范」页面,新人第一篇文档先读规范,能显著降低后续 review 成本。

用 VitePress 建文档站,真正的门槛不在工具而在内容运营:约定好写作规范、把文档更新挂进研发流程,工具链越顺手,内容才越有生命力。

免责声明

本工具与文章内容仅用于学习测试场景,优化建议仅供参考,请勿直接用于生产环境,由此产生的风险自行承担。