Skip to content

实训:用 VitePress 建站

你现在阅读的课程网站(包括本页)就是用 VitePress 构建的。本周我们刚在 markdown 里用 HTML 对照过 Markdown——本实训把这条"内容 → 网站"的流水线亲手走通:安装 VitePress,看 markdown 如何变成 html;引入主题体会样式注入,引入 live demo 插件体会行为注入;最后把它与 WordPress 放在一起比较

元信息

  • 目标:理解"从内容到网站"——markdown 经静态网站生成器(SSG)转为 html 站点;掌握 VitePress 的安装与基本使用;通过主题与插件,体会样式、行为是如何在 md 之外注入的;能对比 VitePress 与 WordPress
  • 关键概念:静态网站生成器(SSG)、构建(build)、主题(theme)、插件(plugin)、部署
  • 关联阶段:cp1
  • 常见误区:以为网站必须有一台"运行中"的服务器(VitePress 的构建产物是纯静态文件);以为样式和行为写进了 markdown(它们在主题层与构建层注入——正是结构与样式、行为分离)

安装与启动

前置:Node 18+(安装见Node 环境构建)。

bash
mkdir mysite && cd mysite
npm init -y
npm add -D vitepress
npx vitepress init     # 向导:目录回车默认,填站点标题,主题选 Default
npm run docs:dev       # 开发服务器,浏览器打开提示的地址

npx vitepress init 生成的骨架:

plain
mysite/
├─ index.md          # 站点首页,也是第一篇 markdown
├─ .vitepress/
│  └─ config.mts     # 站点配置:标题、导航、主题选项
└─ package.json

此后每个 md 文件就是一个页面,文件路径即 URLguide.md/guide)。在编辑器里改一行 index.md,浏览器立刻更新——这就是 markdown 里说过的渲染器在工作,只不过输出的不是一段 html 片段,而是套上导航、侧边栏的完整页面。

从 md 到 html:构建

开发服务器的实时转换只服务于写作;build 才是"从内容到网站"的正式一步:

bash
npm run docs:build    # 产物在 .vitepress/dist/
npm run docs:preview  # 本地预览构建产物

打开 dist/index.html 读源码,对照你的 md:

markdown 侧dist 里的 html 侧
# 标题<h1>标题</h1>,还带上了锚点链接
frontmatter 的 title<title><meta>——元数据进了"head",正如 markdown 所说:frontmatter 是给处理软件读的
每个 md 文件一个 URL、一个完整页面(导航 + 侧边栏 + 正文 + 上/下页)

dist/ 里只有 html/css/js/图片,没有任何需要"运行"的东西——把它扔给任意静态服务器即可上线(见静态Web服务器)。这类"构建时生成静态页面"的工具就叫静态网站生成器(SSG)

引入主题:样式从哪来

你写 md 时从没写过颜色和字体——它们来自主题。想调整默认主题的外观,最常见的办法是覆盖它的 CSS 变量。新建 .vitepress/theme/

plain
.vitepress/theme/
├─ index.mts
└─ custom.css
javascript
// .vitepress/theme/index.mts
import DefaultTheme from 'vitepress/theme'
import './custom.css'
export default DefaultTheme
css
/* .vitepress/theme/custom.css */
:root {
  --vp-c-brand-1: #e05d23;   /* 全站链接与按钮的主色,改我试试 */
}

保存后整个站点换色。注意:你没有改动任何一篇 md——内容在 md,样式在主题,这与本周反复强调的"结构与样式分离"是同一件事在站点层面的重演。想换得更彻底,可以把 export default 换成整个第三方主题包,md 依旧一字不动。

引入插件:行为注入——live demo

本课程网站装了一个行为插件:文档里的 ```html / ```js 围栏不再只是带高亮的静态代码,而是变成可编辑、可运行的沙箱。本页下面这个围栏就是它渲染的(在课程网站上生效):

<!DOCTYPE html>
<html>
<head>
  <title>Parcel Sandbox</title>
  <meta charset="UTF-8" />
  <link rel="stylesheet" href="/styles.css" />
</head>
<body>
  <h1>Hello world</h1>
</body>
</html>

三段配合实现。先装依赖:

bash
npm add -D vitepress-plugin-sandpack
  1. 注册沙箱组件(在 theme/index.mts 里增加):
javascript
import { Sandbox } from 'vitepress-plugin-sandpack'
import 'vitepress-plugin-sandpack/dist/style.css'
// enhanceApp({ app }) { app.component('Sandbox', Sandbox) }
  1. 改写 markdown 渲染管线(本站的真实插件,节选)——markdown-it 把每个围栏交给渲染器,插件拦下 html 围栏、包进 <Sandbox>
javascript
export function liveDemo(md) {
  const defaultFence = md.renderer.rules.fence
  md.renderer.rules.fence = (tokens, idx, opts, env, self) => {
    const token = tokens[idx]
    if (token.info.trim().startsWith('html'))
      return `<Sandbox template="static">${defaultFence(tokens, idx, opts, env, self)}</Sandbox>`
    return defaultFence(tokens, idx, opts, env, self)
  }
}
  1. 在配置里启用
javascript
// config.mts
markdown: { config: (md) => md.use(liveDemo) }

看清它动手的位置:不在浏览器里,而在构建/dev 的渲染管线里——插件是一种"构建期行为",按规则增强写好的内容。这与 WordPress 插件(运行期)有本质区别,正是下节对比的主题之一。

VitePress 与 WordPress:区别与联系

WordPress 是世界上用户最多的建站工具——PHP + MySQL 的内容管理系统(CMS)。两者目标相同:把内容变成网站;路线却相反。

VitePressWordPress
类别静态网站生成器(SSG)内容管理系统(CMS)
内容存放md 文件,跟着 git 走MySQL 数据库,跟着服务器走
页面生成构建时一次性生成静态 html每次访问由 PHP 动态生成 html
样式主题(CSS/组件),构建期生效主题(PHP 模板 + CSS),运行期生效
行为扩展插件:改构建管线插件:挂在服务器请求处理上
写作方式编辑器写 md + git 版本管理浏览器后台所见即所得
部署dist/ 纯静态文件,任意静态服务器/CDN服务器常驻运行 PHP 与数据库
典型场景文档、课程、技术博客门户、商城、社区——内容频繁增改、多人后台协作

联系:殊途同归。

  • 分层相同:两边都是"内容 / 主题(样式)/ 插件(行为)"三层,且都允许换皮、加件而不动内容——你在上两节对 VitePress 做的,正是 WordPress 后台"装主题、装插件"时发生的同构之事
  • 产物相同:浏览器最终收到的都是 html/css/js(呼应 Web软件与BS架构)——区别不在"给浏览器什么",而在"谁、在什么时候生成"
  • 边界互相渗透:WordPress 装缓存插件会把动态页面落成静态文件(向 SSG 逼近);VitePress 也能嵌运行时组件、请求后端 API(向动态伸展)

选型直觉:内容以"写"为主、更新靠 git → SSG;内容频繁增改、要在网页后台管理、多人发帖 → CMS。

验收标准

  • [ ] 本地 docs:dev 跑起来,改一行 md 看到热更新
  • [ ] docs:build 后,在 dist/ 里找到某篇 md 对应的 html,指认 #<h1>、frontmatter → <head> 的对应关系
  • [ ] 覆盖一个主题 CSS 变量并看到全站生效
  • [ ] 能不假思索说出 VitePress 与 WordPress 在内容存放、生成时机、部署形态上的三点区别