跳转到内容

VitePress — Vue 团队用 Vite 写的静态文档站点生成器

待复核

VitePress 是把 markdown 直接变成静态 HTML 站点的工具,专门给”写文档”这件事设计,由 Vue 团队维护。日常类比:像一个会自己排版的印刷机——你写文字稿(markdown),它帮你印成一本电子书(带导航、搜索、代码高亮的网站)。

你写:

# 我的文档
这里是一段说明,下面有代码:
```js
console.log('hello')
跑一行 `npx vitepress build`,VitePress 把这份 .md 转成 .html,附上侧边栏、深色模式、代码高亮、自动生成的目录——一个标准文档站就出来了。
Vue 自己的官网、Pinia、Vitest、VueUse 的文档全部用 VitePress 写——**它就是 Vue 生态脚下的那块地板**。
## 为什么重要
不理解 VitePress 长啥样,下面这些事都会困惑:
- 为什么 docs 站点首屏那么轻——它把"大半是静态 HTML"做到字节级别,浏览器几乎不用先跑一大坨框架
- 为什么写文档可以**直接在 markdown 里塞 Vue 组件**——不用 MDX 那种 JSX 风味语法
- 为什么 Vue 团队会做 Astro / Docusaurus / Nextra 之外的第四种选择——心智不同:markdown 转成 Vue 单文件组件
- 为什么改一行文档几乎瞬时回显——底下是 Vite:浏览器原生加载模块(ESM),改哪块只热替换哪块(HMR)
## 核心要点
VitePress 把"docs 站点"拆成 **三个心脏**:
1. **markdown 转换器**:底下用社区成熟的 markdown-it,上面挂十几个插件按顺序拼出"VitePress 风味"——`:::tip`、文件引用、代码高亮这些都是插件做的。类比:一条流水线,原料从一头进去,每个工位贴一层加工。
2. **双产物静态生成(SSG)**:SSG 就是"先在构建机把页面印成静态 HTML"。它跑两次 Vite build——一次给浏览器(JS/CSS),一次给服务器渲染函数(SSR:在 Node 里先画出 HTML)。同一份源码变两套产物,引擎外包给 Vite。
3. **lean + full 双客户端包**:第一次进页只下 `.lean.js`(hydration:给静态 HTML 接上最小可点交互),站内再跳转才下 `.full.js`(完整组件逻辑)。类比:进门只发名片,要谈合作再拿合同——首屏 JS 常能少三到五成。
主仓核心逻辑大约几千行 TypeScript(不含默认主题),是"框架做减法"的代表作。
## 实践案例
### 案例 1:60 秒起一个 docs 站
```bash
mkdir my-docs && cd my-docs
npm init -y
npm install -D vitepress
npx vitepress init # 选 ./docs、标题、Default theme
npm run docs:dev # http://localhost:5173
npm run docs:build # 输出到 docs/.vitepress/dist
ls docs/.vitepress/dist/assets/chunks/
# 常见会看到 *.<hash>.js 与 *.<hash>.lean.js(文件名含 hash,以实际 dist 为准)

逐部分解释init 生成配置与首页;dev 用 Vite 热更新;build 印出静态站。hashmap.json 把每页映射到内容 hash,用户停在旧页、你刚发新版时能兜底重拉。

案例 2:在 markdown 里直接用 Vue 组件

Section titled “案例 2:在 markdown 里直接用 Vue 组件”

三步:

  1. .vitepress/theme/index.tsenhanceApp 注册全局组件:
import DefaultTheme from 'vitepress/theme'
import Counter from './Counter.vue'
export default {
extends: DefaultTheme,
enhanceApp({ app }) {
app.component('Counter', Counter)
}
}
  1. 任意 .md 里写 <Counter :start="3" />——markdown 会被转成 Vue 单文件组件再渲染。
  2. 为什么必须走 enhanceApp:直接在 .mdimport 浏览器专用代码,构建时服务器渲染会报 window is not defined;注册后 VitePress 才知道怎么在两端安全挂载。

案例 3:最小 markdown-it 插件——把 [[OK]] 换成加粗

Section titled “案例 3:最小 markdown-it 插件——把 [[OK]] 换成加粗”

.vitepress/config.ts

import { defineConfig } from 'vitepress'
export default defineConfig({
markdown: {
config(md) {
md.core.ruler.push('ok-marker', (state) => {
for (const t of state.tokens) {
if (t.type === 'inline' && t.content.includes('[[OK]]')) {
t.content = t.content.replaceAll('[[OK]]', '**OK**')
}
}
})
}
}
})

逐部分解释config(md) 在内置插件之后跑(你最后说话);ruler.push 往解析流水线加一站;写 你好 [[OK]] 构建后会变成加粗的 OK。少见场景可用 preConfig(md) 抢在内置插件之前。

  1. lean / full 双 bundle 的切换由 isInitialPageLoad 驱动:这个标志在 client/app/index.ts 模块级,只在 inBrowser 时重置——SSR 自定义 runner 复用 createApp 时不会清零,后续路由会一直拿 lean 失败

  2. createMarkdownRenderer 是单例if (md) return md 让同一 node 进程只创一个实例。monorepo nx 缓存复用 node worker 时,shiki 主题切换可能不生效——只在 dev server 重启时调 disposeMdItInstance()

  3. 内置 markdown-it 插件的注册顺序就是语义:识别 Vue 组件的插件必须最先(否则组件标签会被转成普通 <p>),代码片段插件必须在代码块外壳插件之前——颠倒会让外壳包错

  4. enhanceApp 钩子很容易漏写:把全局组件直接 import 进 .md,服务器渲染常报 window is not defined——应在 enhanceAppapp.component() 注册;仅浏览器侧的块再用 <ClientOnly> 包住

适用

  • Vue 生态的产品 / 库文档(与 Vue 组件天然衔接)
  • markdown 占 80% 内容、需要少量交互的技术博客
  • 想要极致首屏性能的 docs 站(lean bundle 拍平了 SPA framework 的开销)
  • 对 dev 体验敏感的写作场景(HMR 毫秒级回显)

不适用

  • React / Solid / Svelte 生态项目 → 用 Docusaurus / Nextra / Starlight
  • 内容动态化重的站点(需要 CMS / SSR fetch)→ 用 Nuxt / Next
  • 不写 markdown 的纯 SPA → 直接用 Vite + Vue
  • 需要 MDX 那种 JSX-in-markdown 的项目 → VitePress 用的是 SFC 风格不是 JSX
  • 2018 年:尤雨溪写 VuePress(webpack 底,Vue 2),Vue 官网在它身上痛苦了几年——启动慢、热更新重、依赖一长串自家插件
  • 2020 年:尤雨溪做 Vite(“另起炉灶比改 webpack 容易”),同年 11 月 Vite 1.0 发布
  • 2021 年:顺手起了 VitePress——用 Vite 重写 VuePress 的实验,本意是给 Vue 3 文档用
  • 2024-03:VitePress 1.0 正式发布,成为 Vue 生态官方推荐的文档站方案
  • 2025–2026 年:进入 2.x alpha;社区维护者(如 brc-dd)承担日常主维护,尤雨溪退居次席
  1. 框架的最高境界是做减法——主仓核心不大,因为 markdown 转换、构建、服务器渲染都外包给成熟工具
  2. “双包”是 docs 站点的关键优化——lean 给首屏,full 给交互,分流后首屏字节能掉一个量级
  3. markdown 转 Vue 单文件组件,而不是发明新语法——这是与 MDX 的根本分歧:容器用户已经会,不必再学 JSX-in-markdown
  4. 插件顺序即语义:内置 markdown-it 插件谁先谁后,直接决定语法怎么被解析;顺序是 API 的一部分
  • vite —— Vite 提供 dev server / 双 build / Vite plugin 接口,VitePress 是 Vite 的”应用层用户”
  • vue —— VitePress 用 Vue 做 client runtime,markdown 转出来的就是 Vue SFC
  • markdown-it —— VitePress 的 markdown 内核,17 个插件全挂在它上面
  • shiki —— 代码高亮引擎,VitePress 用 shiki 双主题(light / dark)做语法着色
  • starlight —— Astro 生态的对应物,思路相似(markdown + 组件 + SSG)但底层引擎不同
  • docusaurus —— React 生态的对应物,Meta 维护,更重但功能更全
  • nextra —— Next.js 生态的对应物,MDX-first,VitePress 选了相反的 SFC-first 路线
  • rolldown —— Rust 写的 Rollup 替代品,VitePress 已支持 rolldown-vite
  • astro —— Astro — 内容站点优先的 Web 框架
  • chalk —— chalk — 让 console.log 输出彩色字符串的 Node 库
  • dayjs —— Day.js — 用 2 KB 复刻 Moment 的极简日期库
  • docusaurus —— Docusaurus — 一组 plugin 协作出来的文档站框架
  • echarts —— Apache ECharts — 给一个 JSON 就能画图的可视化库
  • markdown-it —— markdown-it — 把 Markdown 文本变成 HTML 的工业级解析器
  • nextra —— Nextra — 在 Next.js 上盖一层文档站脚手架
  • shiki —— shiki — 把 VS Code 那套染色搬到网页上
  • starlight —— Starlight — Astro 文档站点主题
  • vue —— Vue.js — 渐进式 UI 框架
  • web-vitals —— web-vitals — 让你在自己页面测的数和 Google 排名用的数对得上