- 前端
- 文档
【免费下载链接】vitepress
Vite & Vue powered static site generator.
本指南以 VitePress 官方文档《サイト設定》为骨架,系统梳理应用级(App-Level)站点配置的全部选项——从配置文件解析、站点元数据、路由与构建选项,到主题外观、Markdown/Vite/Vue 集成与五大构建钩子(Build Hooks)。读完本文,你将能够独立完成.vitepress/config.ts的编写、排查构建问题,并借助源码理解每个配置项背后的真实行为,将其用于多语言、子路径部署、SEO 与 PWA 等实战场景。
概述:配置文件的解析与加载
配置文件解析(Config Resolution)
配置文件固定从<root>/.vitepress/config.[ext]解析,其中<root>为项目根目录(即包含.vitepress的目录),[ext]支持.js、.ts、.mjs、.mts四种扩展名,TypeScript 开箱即用。这一点与源码src/node/config.ts中的supportedConfigExtensions = ['js', 'ts', 'mjs', 'mts']完全一致,且解析顺序会同时尝试config/index.[ext]与config.[ext]两种形态。
配置文件推荐使用 ES Modules 语法,并以默认导出(default export)的形式输出配置对象:
export default { // 应用级设置 lang: 'en-US', title: 'VitePress', description: 'Vite & Vue powered static site generator.', ... }resolveConfig(见 src/node/config.ts)会完成以下解析流程:归一化 root 为绝对路径 → 加载用户配置 → 解析站点数据(resolveSiteData)→ 解析srcDir/assetsDir/outDir/cacheDir等路径 → 决定主题目录(存在.vitepress/theme时使用用户主题,否则回退到默认主题DEFAULT_THEME_PATH)→ 解析页面列表。解析后的SiteConfig会挂载到全局global.VITEPRESS_CONFIG,供 content loader 等模块共享。
动态(异步)配置
当配置需要动态生成时,可以默认导出一个(异步)函数:
import { defineConfig } from 'vitepress' export default async () => { const posts = await (await fetch('https://my-cms.com/blog-posts')).json() return defineConfig({ // 应用级设置 lang: 'en-US', title: 'VitePress', description: 'Vite & Vue powered static site generator.', // 主题级设置 themeConfig: { sidebar: [ ...posts.map((post) => ({ text: post.name, link: `/posts/${post.name}` })) ] } }) }也可以直接使用顶层await(Top-Level Await):
import { defineConfig } from 'vitepress' const posts = await (await fetch('https://my-cms.com/blog-posts')).json() export default defineConfig({ // 应用级设置 lang: 'en-US', title: 'VitePress', description: 'Vite & Vue powered static site generator.', // 主题级设置 themeConfig: { sidebar: [ ...posts.map((post) => ({ text: post.name, link: `/posts/${post.name}` })) ] } })从源码看,resolveUserConfig会通过resolveConfigExtends对函数型配置进行求值(typeof config === 'function' ? config() : config),且支持extends字段递归合并基础配置,详见 src/node/config.ts。
配置的智能提示(Config Intellisense)
使用defineConfig辅助函数可以获得 TypeScript 类型补全,在支持的语言服务中,JavaScript 与 TypeScript 文件都能获得提示:
import { defineConfig } from 'vitepress' export default defineConfig({ // ... })其实现位于 src/node/config.ts:defineConfig<ThemeConfig = DefaultTheme.Config>(config)本质上只是返回传入的配置对象,借助泛型默认值将类型约束到默认主题的配置结构。
带类型的主题配置(Typed Theme Config)
默认情况下,defineConfig假定主题配置的类型为DefaultTheme.Config:
import { defineConfig } from 'vitepress' export default defineConfig({ themeConfig: { // 类型为 `DefaultTheme.Config` } })使用自定义主题并希望对其themeConfig做类型检查时,改用defineConfigWithTheme并通过泛型传入自定义主题的配置类型:
import { defineConfigWithTheme } from 'vitepress' import type { ThemeConfig } from 'your-theme' export default defineConfigWithTheme<ThemeConfig>({ themeConfig: { // 类型为 `ThemeConfig` } })注意源码中defineConfigWithTheme已被标注为@deprecated use defineConfig instead(src/node/config.ts),但从当前文档与类型层面它依然可用;推荐新代码直接使用defineConfig<ThemeConfig>({ ... })的泛型写法。
Vite・Vue・Markdown 的配置入口
- Vite:无需单独的 Vite 配置文件,直接在 VitePress 配置的 vite 选项中提供 Vite 配置。类型为
import('vite').UserConfig。 - Vue:VitePress 内置了官方 Vue 插件
@vitejs/plugin-vue,其选项通过 vue 传入。类型为import('@vitejs/plugin-vue').Options。 - Markdown:默认的 Markdown-It 实例可通过 markdown 选项自定义,选项类型为
MarkdownOption(源码定义见 src/node/markdown/markdown.ts)。
站点元数据(Site Metadata)
title
- 类型:
string - 默认值:
VitePress - 页面级覆盖:frontmatter 的 title
站点的标题。默认主题会将其显示在导航栏中。若未定义titleTemplate,它还会作为每个页面标题的默认后缀。各页面最终标题 = 该页首个<h1>标题文本 + 全局title后缀。例如:
export default { title: 'My Awesome Site' }# Hello该页面的标题即为Hello | My Awesome Site。源码中默认值由 src/node/config.ts 的userConfig.title || 'VitePress'提供。
titleTemplate
- 类型:
string | boolean - 页面级覆盖:frontmatter 的 titleTemplate
用于定制每个页面标题的后缀或整体标题。例如:
export default { title: 'My Awesome Site', titleTemplate: 'Custom Suffix' }# Hello页面标题为Hello | Custom Suffix。若要完全自定义标题的渲染方式,可在titleTemplate中使用:title符号:
export default { titleTemplate: ':title - Custom Suffix' }其中:title会被替换为从页面首个<h1>推断出的文本,上面的例子将渲染为Hello - Custom Suffix。设置为false可禁用标题后缀。
description
- 类型:
string - 默认值:
A VitePress site - 页面级覆盖:frontmatter 的 description
站点的描述,会以<meta>标签输出到页面 HTML 中:
export default { description: 'A VitePress site' }对应源码默认值见 src/node/config.ts:userConfig.description || 'A VitePress site'。
head
- 类型:
HeadConfig[] - 默认值:
[] - 页面级追加:frontmatter 的 head
向页面 HTML 的<head>中额外输出的元素。用户添加的标签会渲染在 VitePress 自带标签之后、</head>之前。其类型定义为:
type HeadConfig = | [string, Record<string, string>] | [string, Record<string, string>, string]即三元组形式[标签名, 属性对象, 可选的内联内容],实际类型声明见 types/shared.d.ts。需要注意:resolveSiteDataHead(src/node/config.ts)会自动在 head 中注入check-dark-mode与check-mac-os两个内联脚本(MPA 模式下仅注入后者),因此实际输出的<head>会比用户配置的多出这些由框架管理的元素。
示例:添加 favicon
export default { head: [['link', { rel: 'icon', href: '/favicon.ico' }]] } // favicon.ico 需放在 public 目录;若设置了 base,则使用 /base/favicon.ico /* 输出结果: <link rel="icon" href="/favicon.ico"> */示例:添加 Google Fonts
export default { head: [ [ 'link', { rel: 'preconnect', href: 'https://fonts.googleapis.com' } ], [ 'link', { rel: 'preconnect', href: 'https://fonts.gstatic.com', crossorigin: '' } ], [ 'link', { href: 'https://fonts.googleapis.com/css2?family=Roboto&display=swap', rel: 'stylesheet' } ] ] } /* 输出结果: <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Roboto&display=swap" rel="stylesheet"> */示例:注册 Service Worker
export default { head: [ [ 'script', { id: 'register-sw' }, `;(() => { if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js') } })()` ] ] } /* 输出结果: <script id="register-sw"> ;(() => { if ('serviceWorker' in navigator) { navigator.serviceWorker.register('/sw.js') } })() </script> */示例:接入 Google Analytics
export default { head: [ [ 'script', { async: '', src: 'https://www.googletagmanager.com/gtag/js?id=TAG_ID' } ], [ 'script', {}, `window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'TAG_ID');` ] ] } /* 输出结果: <script async src="https://www.googletagmanager.com/gtag/js?id=TAG_ID"></script> <script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'TAG_ID'); </script> */lang
- 类型:
string - 默认值:
en-US
站点的语言属性,会输出为页面 HTML 的<html lang="en-US">:
export default { lang: 'en-US' }base
- 类型:
string - 默认值:
/
站点部署的基础 URL。当部署在子路径下(如 GitHub Pages 的https://foo.github.io/bar/)时,需要将base设为'/bar/',且必须以/开头和结尾。base会自动添加到其他选项中以/开头的 URL 之前,因此只需设置一次:
export default { base: '/base/' }源码中的normalizeSiteBase(src/node/config.ts)会做归一化处理:自动补末尾斜杠;若 base 以.开头但并非精确的'./'相对形式(isRelativeBase)则直接抛错;不是相对 base 且不是外部 URL、又不以/开头时自动补前导斜杠。因此除了/bar/这类绝对子路径,还可以使用'./'相对 base 让产物可移动到任意子路径下部署。
路由(Routing)
cleanUrls
- 类型:
boolean - 默认值:
false
设为true后,URL 末尾的.html会被移除,同时参见生成干净 URL一节。
::: warning 需要服务器配置 某些托管环境需要额外配置:访问/foo时能不经过重定向直接返回/foo.html。 :::
源码层面,cleanUrls的默认解析见 src/node/config.ts(cleanUrls: !!userConfig.cleanUrls)。另外当base为相对路径且cleanUrls开启时,构建阶段会输出警告(cleanUrls with a relative base needs server-side rewrites and breaks file:// browsing,见 src/node/config.ts),提示相对 base 与 cleanUrls 组合需要服务端重写支持。
rewrites
- 类型:
Record<string, string>
定义目录与 URL 之间的自定义映射,详见路由:路由重写:
export default { rewrites: { 'source/:page': 'destination/:page' } }从类型定义看,rewrites还支持函数形式((id: string) => string)(见 src/node/siteConfig.ts),解析后会生成正反向两张映射表map/inv挂在SiteConfig.rewrites上。
构建(Build)
srcDir
- 类型:
string - 默认值:
.
存放 Markdown 页面源码的目录(相对于项目根目录),参见根目录与源码目录:
export default { srcDir: './src' }srcExclude
- 类型:
string[] - 默认值:
undefined
匹配要从源码中排除的 Markdown 文件的 glob 模式(语法参考 fast-glob):
export default { srcExclude: ['**/README.md', '**/TODO.md'] }outDir
- 类型:
string - 默认值:
./.vitepress/dist
构建输出目录(相对于项目根目录):
export default { outDir: '../public' }assetsDir
- 类型:
string - 默认值:
assets
生成资源(构建产物)存放的子目录名,路径相对于outDir内部解析:
export default { assetsDir: 'static' }源码 src/node/config.ts 会校验assetsDir解析后必须位于outDir之内,否则抛出assetsDir cannot be set to a location outside of the outDir错误。
cacheDir
- 类型:
string - 默认值:
./.vitepress/cache
缓存文件目录(相对于项目根目录),参考 Vite 的 cacheDir:
export default { cacheDir: './.vitepress/.vite' }ignoreDeadLinks
- 类型:
boolean | 'localhostLinks' | (string | RegExp | ((link: string, source: string) => boolean))[] - 默认值:
false
设为true时,存在死链也不会导致构建失败。设为'localhostLinks'时,仅跳过对localhost链接的检查,其他死链仍会使构建失败:
export default { ignoreDeadLinks: true }也可以指定为精确 URL 字符串、正则表达式、自定义过滤函数组成的数组:
export default { ignoreDeadLinks: [ // 精确忽略 "/playground" '/playground', // 忽略所有 localhost 链接 /^https?:\/\/localhost/, // 忽略路径中包含 "/repl/" 的链接 /\/repl\//, // 自定义函数: 忽略包含 "ignore" 的链接 (url) => { return url.toLowerCase().includes('ignore') } ] }类型定义中该过滤函数签名为(link: string, source: string) => boolean(见 src/node/siteConfig.ts),即第二个参数还能拿到链接所在源文件的信息,便于做更精细的判定。
mpa
- 类型:
boolean - 默认值:
false
设为true时,生产构建将以 MPA 模式进行。MPA 模式默认以 0kb 客户端 JavaScript 交付页面,代价是禁用客户端导航,需要交互的页面必须显式选择接入(opt-in)。其类型定义标注为@experimental,默认解析见 src/node/config.ts(mpa: !!userConfig.mpa)。
主题相关(Theming)
appearance
- 类型:
boolean | 'dark' | 'force-dark' | 'force-auto' | import('@vueuse/core').UseDarkOptions - 默认值:
true
是否启用深色模式(在<html>上添加.dark类):
true:跟随用户的环境偏好。'dark':默认使用深色,用户仍可切换。false:用户无法切换主题。'force-dark':始终固定深色(不可切换)。'force-auto':始终跟随系统偏好(不可切换)。
该选项会插入一个内联脚本,从本地存储vitepress-theme-appearance(常量APPEARANCE_KEY定义于 src/shared/shared.ts)恢复外观设置,从而在页面渲染前应用.dark类以防止闪烁(FOUC)。appearance.initialValue仅支持'dark' | undefined,不能使用 Ref 或 getter。
源码实现值得展开:resolveSiteDataHead(src/node/config.ts)在appearance非空时自动注入id="check-dark-mode"的内联脚本,脚本内容根据 appearance 模式分为三种——force-dark直接加类;force-auto通过matchMedia('(prefers-color-scheme: dark)')判定;普通模式则优先读localStorage的vitepress-theme-appearance,再回退到initialValue ?? 'auto'。另外注意 MPA 模式下(userConfig?.mpa为真)该脚本不会被注入。
lastUpdated
- 类型:
boolean - 默认值:
false
使用 Git 获取每个页面的最后更新时间戳。时间戳会包含在每页数据中,可通过useData引用。使用默认主题时开启该选项会在页面底部显示最后更新时间,文案可通过themeConfig.lastUpdated.text定制。
源码中lastUpdated的解析为userConfig.lastUpdated ?? !!userConfig.themeConfig?.lastUpdated(src/node/config.ts),即只要任一处开启即生效,其底层时间戳获取逻辑位于 src/node/utils/getGitTimestamp.ts。
自定义(Customization)
markdown
- 类型:
MarkdownOption
Markdown 解析器的配置。VitePress 使用 Markdown-it 作为解析器、Shiki 做语法高亮,可按需指定各类 Markdown 相关选项:
export default { markdown: {...} }可用的选项可查看类型定义与 JSDoc。这里结合源码给出高频选项速查:
preConfig/config:在应用内置插件之前/之后配置 markdown-it 实例的回调;theme:语法高亮主题,支持{ light: 'github-light', dark: 'github-dark' }双主题对象,默认即为此双主题(src/node/markdown/markdown.ts);lineNumbers:代码块行号(依赖preWrapper,默认false);snippet/include:<<<代码片段导入与<!-- @include: path -->Markdown 包含;emoji、tasklist、footnote、attrs、anchor、toc、math、container、gfmAlerts、image、component、frontmatter、sfc等开关;externalLinks:外部链接属性,默认{ target: '_blank', rel: 'noreferrer' }(src/node/markdown/markdown.ts)。
vite
- 类型:
import('vite').UserConfig
向内部的 Vite 开发服务器/打包器传入原始的 Vite Config:
export default { vite: { // Vite 配置 } }vue
- 类型:
import('@vitejs/plugin-vue').Options
将选项原样传给内部的@vitejs/plugin-vue实例:
export default { vue: { // @vitejs/plugin-vue 选项 } }构建钩子(Build Hooks)
VitePress 的构建钩子可用于为站点添加功能或行为,官方文档列出的典型用途包括:
- 站点地图(Sitemap)
- 搜索索引(Search index)
- PWA
- Teleport(SSG 期间传送内容的处理)
buildEnd
- 类型:
(siteConfig: SiteConfig) => Awaitable<void>
buildEnd是构建 CLI 钩子:在构建(SSG)完成之后、VitePress CLI 进程退出之前执行:
export default { async buildEnd(siteConfig) { // ... } }适合在此生成 RSS feed 等一次性收尾任务(类型注释见 src/node/siteConfig.ts)。
postRender
- 类型:
(context: SSGContext) => Awaitable<SSGContext | void>
postRender是 SSG 渲染完成时调用的构建钩子,可用于处理 SSG 期间的 teleport 内容:
export default { async postRender(context) { // ... } }interface SSGContext { content: string teleports?: Record<string, string> [key: string]: any }类型声明见 types/shared.d.ts,其中还包含框架内部使用的vpIcons: Set<string>(SSR 期间通过useIcon注册的图标集合)。
transformHead
- 类型:
(context: TransformContext) => Awaitable<HeadConfig[]>
transformHead是在生成每个页面之前转换 head 的构建钩子,可添加无法在配置文件中静态声明的 head 元素。只需返回新增的部分,框架会自动与既有 head 合并。
::: warning 不要修改context内的值。 :::
export default { async transformHead(context) { // ... } }interface TransformContext { page: string // 例如: index.md(相对于 srcDir) assets: string[] // 已解析的公开 URL(非 js/css 资源) siteConfig: SiteConfig siteData: SiteData pageData: PageData title: string description: string head: HeadConfig[] content: string }该钩子只在静态站点生成(build)阶段调用,开发模式下不会执行。若需在开发模式下动态添加 head 元素,改用transformPageData:
export default { transformPageData(pageData) { pageData.frontmatter.head ??= [] pageData.frontmatter.head.push([ 'meta', { name: 'og:title', content: pageData.frontmatter.layout === 'home' ? `VitePress` : `${pageData.title} | VitePress` } ]) } }示例:添加规范 URL 的<link>
export default { transformPageData(pageData) { const canonicalUrl = `https://example.com/${pageData.relativePath}` .replace(/index\.md$/, '') .replace(/\.md$/, '.html') pageData.frontmatter.head ??= [] pageData.frontmatter.head.push([ 'link', { rel: 'canonical', href: canonicalUrl } ]) } }transformHtml
- 类型:
(code: string, id: string, context: TransformContext) => Awaitable<string | void>
transformHtml是在每个页面的内容写入磁盘之前进行转换的构建钩子。
::: warning 不要修改context内的值。此外,修改 HTML 可能引发运行时水合(hydration)问题。 :::
export default { async transformHtml(code, id, context) { // ... } }transformPageData
- 类型:
(pageData: PageData, context: TransformPageContext) => Awaitable<Partial<PageData> | { [key: string]: any } | void>
transformPageData是转换每个页面pageData的钩子,既可以就地修改pageData,也可以返回变更值让其合并:
::: warning 不要修改context内的值。若在其中执行网络请求或重计算(如图像生成),会影响开发服务器的性能,可考虑用process.env.NODE_ENV === 'production'做条件分支。 :::
export default { async transformPageData(pageData, { siteConfig }) { pageData.contributors = await getPageContributors(pageData.relativePath) } // 或者返回待合并的值 async transformPageData(pageData, { siteConfig }) { return { contributors: await getPageContributors(pageData.relativePath) } } }interface TransformPageContext { siteConfig: SiteConfig }从源码注释看(src/node/siteConfig.ts),该钩子在开发与构建两种模式下渲染 Markdown 到 Vue 时都会被调用,返回的变更值会合并进页面数据——这正是它在开发模式下也能生效的原因。
结语:从配置到行为的关键路径
回顾全文,VitePress 的站点配置并非一份"写了就完事"的清单,而是一条可追踪的代码路径:defineConfig提供类型约束 →resolveUserConfig/resolveConfig完成文件加载、路径归一化与默认值填充 →resolveSiteData产出运行时站点数据 →createMarkdownRenderer按markdown选项装配解析器与插件 → 构建钩子(buildEnd/postRender/transformHead/transformHtml/transformPageData)在 SSG 流水线的各个节点介入。掌握这条链路之后,无论是排查 base 路径问题、定制 head、注入动态元数据,还是接入 PWA 与站点地图,都能在 src/node/config.ts、src/node/siteConfig.ts 与 src/node/markdown/markdown.ts 中找到对应的实现依据,从而让配置从"照抄示例"升级为"可解释、可扩展"。
- 前端
- 文档
【免费下载链接】vitepress
Vite & Vue powered static site generator.
相关推荐
Video2X 6.0.0终极指南:如何利用C/C++重构实现视频无损放大300%加速
Video2X 6.0.0终极指南:如何利用C/C++重构实现视频无损放大300%加速 你是否曾为低分辨率视频的模糊画面而烦恼?或者想将老旧的视频素材提升到4K
前端文档Zola 站点配置完全指南:zola.toml 全量参数详解与源码级原理
Zola 站点配置完全指南:zola.toml 全量参数详解与源码级原理 Zola 是一个把"SSG(静态站点生成器)"压缩进单个二进制的快速建站工具,其哲学是
静态站点CLI开发工具wagmi 中 createConfig 完全指南:配置项详解、Config 状态模型与源码级原理
wagmi 中 createConfig 完全指南:配置项详解、Config 状态模型与源码级原理 createConfig 是 wagmi 的核心入口函数,用
区块链Web3前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考