VitePress Site Config 完全指南:站点级配置项全解与源码级原理剖析
2026/9/21 12:01:38 网站建设 项目流程

VitePress Site Config 完全指南:站点级配置项全解与源码级原理剖析

【免费下载链接】vitepressVite & Vue powered static site generator.项目地址: https://gitcode.com/gh_mirrors/vi/vitepress

Site Config 是 VitePress 站点全局配置的入口,它定义了独立于主题的通用设置——从站点标题、<head>标签、多语言到构建产物路径与 CDN 资源分发,再到构建钩子与页面数据变换。本文以官方参考文档为主体,结合当前仓库的 配置解析源码 与 类型声明,逐项讲解每个配置选项的类型、默认值、可覆盖层级,并给出可直接复制的实战示例,帮助你完全掌握 VitePress 的站点级配置体系。

配置解析机制:配置文件从哪来

VitePress 的配置文件始终从<root>/.vitepress/config.[ext]解析,其中<root>是你的 VitePress 项目根目录,[ext]是受支持的扩展名之一。

在 src/node/config.ts 中可以看到,受支持的配置文件扩展名被硬编码为:

const supportedConfigExtensions = ['js', 'ts', 'mjs', 'mts']

也就是说 TypeScript 开箱即用,无需任何额外配置。此外,config/index.[ext]config.[ext]两种形态都会被识别,解析顺序是先index目录形态再顶层文件形态(见 resolveUserConfig)。

配置解析发生在resolveConfig中:它会读取用户配置、归一化rootsrcDirassetsDiroutDircacheDir等路径,解析站点数据,并最终构建出完整的SiteConfig对象(包含pagesrewritesdynamicRoutes等派生信息),同时把配置挂到全局VITEPRESS_CONFIG上供内容加载器共享。

推荐使用 ES Modules 语法

配置文件的入口应该默认导出一个对象:

export default { // app level config options lang: 'en-US', title: 'VitePress', description: 'Vite & Vue powered static site generator.', ... }

从源码看,resolveConfigExtends会先判断配置是否为函数并调用它(typeof config === 'function' ? config() : config),因此以下两种“动态配置”写法都被支持,可用于从 CMS、远程接口等动态生成配置:

方式一:默认导出 async 函数

import { defineConfig } from 'vitepress' export default async () => { const posts = await (await fetch('https://my-cms.com/blog-posts')).json() return defineConfig({ // app level config options lang: 'en-US', title: 'VitePress', description: 'Vite & Vue powered static site generator.', // theme level config options themeConfig: { sidebar: [ ...posts.map((post) => ({ text: post.name, link: `/posts/${post.name}` })) ] } }) }

方式二:顶层await(需要 ESM 环境)

import { defineConfig } from 'vitepress' const posts = await (await fetch('https://my-cms.com/blog-posts')).json() export default defineConfig({ // app level config options lang: 'en-US', title: 'VitePress', description: 'Vite & Vue powered static site generator.', // theme level config options themeConfig: { sidebar: [ ...posts.map((post) => ({ text: post.name, link: `/posts/${post.name}` })) ] } })

配置继承:extends

UserConfig还提供了extends选项(见 siteConfig.ts),用于继承一份基础配置,其值会被递归合并并被当前配置覆盖。resolveConfigExtends会递归解析extends链并调用mergeConfig完成合并——数组会拼接,对象会递归合并,其中vitemarkdown走专门的合并逻辑。这非常适合多个站点共享一份公共主题基座配置的场景。

配置智能提示与类型化主题配置

Config Intellisense:defineConfig

使用defineConfig辅助函数即可获得基于 TypeScript 的配置项智能提示。在 JavaScript 与 TypeScript 中均可用(前提是 IDE 支持):

import { defineConfig } from 'vitepress' export default defineConfig({ // ... })

源码层面的实现非常简单(config.ts):

export function defineConfig<ThemeConfig = DefaultTheme.Config>( config: UserConfig<NoInfer<ThemeConfig>> ) { return config }

它本身不改变运行时行为,纯粹提供类型约束与提示。

Typed Theme Config:defineConfigWithTheme

默认情况下,defineConfig期望的themeConfig类型来自默认主题(DefaultTheme.Config):

import { defineConfig } from 'vitepress' export default defineConfig({ themeConfig: { // Type is `DefaultTheme.Config` } })

如果你使用自定义主题并希望themeConfig获得类型检查,需要使用defineConfigWithTheme并通过泛型参数传入自定义主题的配置类型:

import { defineConfigWithTheme } from 'vitepress' import type { ThemeConfig } from 'your-theme' export default defineConfigWithTheme<ThemeConfig>({ themeConfig: { // Type is `ThemeConfig` } })

从源码注释可以看到该函数已被标记为@deprecated(config.ts),官方推荐改用泛型化的defineConfig,但该 API 仍被保留以兼容自定义主题场景。

Vite、Vue 与 Markdown 的配置入口

Site Config 提供了三个“透传”选项,让你无需创建独立的 Vite 配置文件:

  • Vite:使用配置中的vite选项配置底层 Vite 实例,无需单独的 Vite 配置文件;
  • Vue:VitePress 已内置官方 Vue 插件@vitejs/plugin-vue,可通过vue选项配置其参数;
  • Markdown:可通过markdown选项配置底层的 Markdown-It 解析器实例。

页面级与目录级覆盖

页面级覆盖(Frontmatter)

部分设置可以通过页面 frontmatter 覆盖,详见 Frontmatter 配置。

目录级覆盖(additionalConfig)

部分配置可以在目录层级覆盖,使该目录下所有页面共享设置,而无需在每个页面的 frontmatter 中重复声明。

实现方式是:在相关目录中添加一个名为config.ts(或.js.mjs.mts)的文件,用export default导出配置对象,与主配置文件类似。嵌套目录会继承父目录的设置,覆盖项会被合并。

defineAdditionalConfig辅助函数可为可用选项提供 TypeScript 智能提示(与defineConfig一样,使用是可选的)。

例如,对于一个多语言站点,我们希望每种语言有各自的description,可以在es/config.ts中写入:

import { defineAdditionalConfig } from 'vitepress' export default defineAdditionalConfig({ description: 'Generador de Sitios Estáticos desarrollado con Vite y Vue.' })

这样es目录下所有页面都会使用该description

源码实现细节:目录级配置的收集在 gatherAdditionalConfig 中完成——它通过 glob 模式**/config.{js,mjs,ts,mts}srcDir下扫描所有config.*文件(受srcExclude过滤),逐个加载并按键(目录路径)聚合成additionalConfig字典。合并发生在resolveSiteDataByRoute(见 shared.ts):它会按“additionalConfig 栈 → locale 配置 → 根配置”的顺序叠加,目录越深优先级越高(配置按目录路径排序,深层目录覆盖浅层)。该功能由UserConfig.additionalConfig选项控制,可显式设置为{}来关闭自动收集。

另外,使用内置 i18n 功能时,语言目录的设置也可以通过主配置文件中的locales设置覆盖,详见 国际化指南。

站点元数据(Site Metadata)

title

  • 类型:string
  • 默认值:VitePress
  • 可通过 frontmatter 或目录级配置覆盖

站点的标题。使用默认主题时,它会显示在导航栏中。同时它也是所有页面标题的默认后缀,除非定义了titleTemplate。页面最终标题由页面第一个<h1>的文本内容加上全局title后缀组成。例如:

export default { title: 'My Awesome Site' }
# Hello

页面标题将是Hello | My Awesome Site

源码实现:默认值在 resolveSiteData 中体现(userConfig.title || 'VitePress');标题拼接逻辑在 createTitle 中实现,true/undefined模板默认拼| ${siteTitle}后缀。

titleTemplate

  • 类型:string | boolean
  • 可通过 frontmatter 或目录级配置覆盖

用于自定义每个页面的标题后缀或整个标题。例如:

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 或目录级配置覆盖

站点的描述,会渲染为页面 HTML 中的<meta>标签:

export default { description: 'A VitePress site' }

head

  • 类型:HeadConfig[]
  • 默认值:[]
  • 可通过 frontmatter 或目录级配置追加

额外的<head>标签元素。用户添加的标签会渲染在 VitePress 自带标签之后、</head>闭合标签之前。

类型定义为(见 types/shared.d.ts):

type HeadConfig = | [string, Record<string, string>] | [string, Record<string, string>, string]

[标签名, 属性对象][标签名, 属性对象, 内联内容]的元组。

合并与去重规则:来自站点配置、locale 配置、目录级配置、frontmatter 和transformHead的 head 条目按此顺序合并。后出现的条目会替换(而非追加)同 key 的先前条目:

  • 带有id属性的元素以id为 key;
  • 没有idmeta元素以content之外的第一个属性(如namepropertyhttp-equiv)及其值为 key。

其他元素永不参与去重。如果想渲染多个会共享 key 的meta标签(比如多个<meta name="author">),请给每个标签一个唯一的id

去重逻辑的具体实现见 mergeHead 与 getHeadKey:getHeadKey正是按上述规则提取 key,mergeHead通过Map<key, index>实现“同 key 替换、无 key 追加”。

示例:添加 favicon
export default { head: [['link', { rel: 'icon', href: '/favicon.ico' }]] } // put favicon.ico in public directory, if base is set, use /base/favicon.ico /* Would render: <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' } ] ] } /* Would render: <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') } })()` ] ] } /* Would render: <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');` ] ] } /* Would render: <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
  • 可在目录级配置覆盖

站点的lang属性,渲染为<html lang="en-US">

export default { lang: 'en-US' }

dir

  • 类型:'ltr' | 'rtl' | 'auto'
  • 默认值:ltr
  • 可在目录级配置覆盖;也可通过 frontmatter 按页覆盖

站点的文本方向,渲染为<html dir="rtl">。默认主题会为从右到左的语言镜像其布局。参见 RTL 支持。

export default { dir: 'rtl' }

base

  • 类型:string
  • 默认值:/

站点部署的基础 URL。如果你的站点部署在子路径下(例如 GitHub Pages),需要设置此项。若部署到https://foo.github.io/bar/,则应设置base'/bar/'。它应该始终以斜杠开头和结尾。

唯一的例外是'./',它会产生可搬迁构建(relative base):页面以自身位置为基准引用所有资源,因此同一份构建产物可以从任意子路径(IPFS 网关、归档等)直接使用,无需重新构建,也能在从文件系统直接打开时正常浏览。

base会自动前置到其他选项中所有以/开头的 URL 上,所以只需指定一次:

export default { base: '/base/' }

也可以通过命令行按构建指定:vitepress build --base /base/

源码实现:归一化逻辑在 normalizeSiteBase 中——自动补全结尾斜杠、非/开头时补前缀;同时校验相对 base 必须是精确的'./',否则抛错。另外,相对 base 与cleanUrls同时开启时,构建会给出警告(因为file://浏览与干净 URL 不兼容,见 config.ts)。

路由(Routing)

cleanUrls

  • 类型:boolean
  • 默认值:false

设为true时,VitePress 会从 URL 中移除.html后缀。参见 生成干净 URL。

⚠️ 需要服务器支持启用此功能可能需要宿主平台做额外配置:服务器必须能在访问/foo不经过重定向直接返回/foo.html的内容。

rewrites

  • 类型:Record<string, string>

定义自定义的目录 ↔ URL 映射。参见 路由重写:

export default { rewrites: { 'source/:page': 'destination/:page' } }

从类型定义看(siteConfig.ts),rewrites也支持函数形式(id: string) => string,用于以编程方式计算目标路径。解析后SiteConfig会同时维护map(源路径 → 重写路径)与inv(反向)两张表(siteConfig.ts)。

构建(Build)

srcDir

  • 类型:string
  • 默认值:.

存放 Markdown 页面的目录,相对于项目根目录。参见 根目录与源目录:

export default { srcDir: './src' }

srcExclude

  • 类型:string[]
  • 默认值:undefined

用于匹配应从源内容中排除的 Markdown 文件的 glob 模式:

export default { srcExclude: ['**/README.md', '**/TODO.md'] }

outDir

  • 类型:string
  • 默认值:./.vitepress/dist

站点构建输出位置,相对于项目根目录:

export default { outDir: '../public' }

assetsDir

  • 类型:string
  • 默认值:assets

指定生成的静态资源所嵌套的目录。该路径应在outDir内部,并相对于它解析:

export default { assetsDir: 'static' }

源码校验resolveConfig会计算resolvedAssetsDir = outDir/assetsDir,若该路径不在outDir之内会直接抛错(见 config.ts),确保assetsDir不能指向outDir之外。

assetsBase

  • 类型:string
  • 默认值:undefined

生成的资源(assetsDir下的所有内容)所服务的 URL 前缀——典型场景是 CDN。必须是绝对 URL、协议相对 URL 或根绝对路径;缺少结尾斜杠时会被自动补上。

export default { base: '/', assetsBase: 'https://cdn.example.com/' // scripts, styles, fonts and imported images resolve to // https://cdn.example.com/assets/* }

发出的资源 URL 为assetsBase拼接输出相对路径,因此 CDN 应镜像outDir的目录结构(上传outDir/assets,使其可通过<assetsBase>/assets/*访问)。HTML 页面、Markdown 链接、public目录文件以及hashmap.json仍使用base

assetsBase指向其他源时,VitePress 会给发出的 script 与 preload 标签加上crossorigin属性——CDN 必须为你的站点源发送Access-Control-Allow-Origin响应头(模块脚本始终以 CORS 模式请求)。

使用注意:该选项只影响生产构建。vitepress preview对根绝对路径形式的assetsBase(如/cdn/)从本地 dist 提供;外部 URL 则按真实地址请求。也可以通过命令行指定:vitepress build --assetsBase https://cdn.example.com/

源码实现normalizeAssetsBase(config.ts)会补全结尾斜杠,并校验必须是绝对 URL、协议相对 URL 或根绝对路径,否则抛错。归一化结果存入SiteConfig.assetsBase

assetsShards

  • 类型:number
  • 默认值:undefined

将生成的资源分散到assetsDir下的这么多个子目录中(assets/0/assets/N-1/),而不是一个扁平目录。适用于主机对每个目录的文件数量设限的场景——例如 Netlify 允许 54,000 个文件。每个页面会产出两个 JavaScript 文件,因此一个 60,000 页的站点至少需要 3 个 shard,并留出一定余量(因为文件按名称哈希分布)。

export default { assetsShards: 4 }

共享 chunk 保留在assets/chunks/中。一个文件属于哪个 shard 只取决于它的文件名,因此未变化的文件在构建之间 URL 保持稳定。只影响生产构建。

源码校验assetsShards必须是大于 1 的整数,否则构建报错(config.ts)。客户端通过 hashmap 中带 shard 前缀的条目定位 chunk,无需猜测目录布局(见 pageChunkPath)。

icons

  • 类型:{ include?: string[] }

生成图标样式的选项。构建时会收集 SSR 期间渲染出的每一个 iconify 图标。名称以完全限定的collection:name形式书写,并对照项目依赖中声明的@iconify-json/*包解析。

仅在客户端渲染的图标——例如在<ClientOnly>内部、或水合之后才渲染的图标——对 SSR 收集是不可见的。把它们列入include以强制加入样式表:

export default { icons: { include: ['mdi:home', 'simple-icons:discord'] } }

cacheDir

  • 类型:string
  • 默认值:./.vitepress/cache

缓存文件目录,相对于项目根目录。参见 Vite 的 cacheDir 选项:

export default { cacheDir: './.vitepress/.vite' }

ignoreDeadLinks

  • 类型:boolean | 'localhostLinks' | (string | RegExp | ((link: string, source: string) => boolean))[]
  • 默认值:false

设为true时,VitePress 不会因为死链而构建失败。

设为'localhostLinks'时,构建仍会因死链失败,但不检查localhost链接。

export default { ignoreDeadLinks: true }

也可以是精确 URL 字符串、正则模式或自定义过滤函数的数组:

export default { ignoreDeadLinks: [ // ignore exact url "/playground" '/playground', // ignore all localhost links /^https?:\/\/localhost/, // ignore all links include "/repl/"" /\/repl\//, // custom function, ignore all links include "ignore" (url) => { return url.toLowerCase().includes('ignore') } ] }

注意:自定义过滤函数接收(link, source)两个参数,source是链接所在页面的标识。

mpa(实验性)

  • 类型:boolean
  • 默认值:false

设为true时,生产应用将以 MPA 模式 构建。MPA 模式默认提供 0kb JavaScript,代价是禁用客户端导航,交互能力需要显式选择启用。

主题(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这个 localStorage key 恢复用户设置。这确保.dark类在页面渲染之前就被应用,避免闪烁。

appearance.initialValue只能是'dark' | undefined;不支持 ref 或 getter。

源码实现APPEARANCE_KEY = 'vitepress-theme-appearance'定义在 src/shared/shared.ts。内联脚本由 resolveSiteDataHead 注入:根据配置生成check-dark-mode脚本,分别处理force-darkforce-auto与普通localStorage + prefers-color-scheme三种分支;同时在appearance未禁用时还会注入check-mac-os脚本用于平台类名。

lastUpdated

  • 类型:boolean
  • 默认值:false

是否使用 Git 获取每个页面的最后更新时间戳。该时间戳会包含在每个页面的 page data 中,可通过useData访问。

使用默认主题时,启用该选项会在每个页面显示最后更新时间。可通过themeConfig.lastUpdated.text自定义显示文本。

值得注意的是,从 resolveConfig 的实现看,lastUpdated默认值实际上是userConfig.lastUpdated ?? !!userConfig.themeConfig?.lastUpdated——即顶层未显式设置时,会回退到themeConfig.lastUpdated的值。

定制(Customization)

markdown 配置透传

  • 类型:MarkdownOption

配置 Markdown 解析器选项。VitePress 使用 Markdown-It 作为解析器,并使用 Shiki 做语法高亮。在该选项中可传入各种 Markdown 相关选项:

export default { markdown: {...} }

全部可用选项可查看类型声明与 JSDoc,对应的实现文件为 src/node/markdown/markdown.ts。

markdown.headers设为true或传入@mdit-vue/plugin-headers的选项,可以收集标题到useData().page.headers。该选项默认禁用。

vite 配置透传

  • 类型:import('vite').UserConfig

将原始 Vite Config 传给内部 Vite dev server / bundler:

export default { vite: { // Vite config options } }

mergeConfig中,根层级的vite键会交给 Vite 的mergeConfig深度合并(config.ts),configFile还可以指向额外的 Vite 配置文件或设为false禁用加载。

vue 配置透传

  • 类型:import('@vitejs/plugin-vue').Options

将原始@vitejs/plugin-vue选项传给内部插件实例:

export default { vue: { // @vitejs/plugin-vue options } }

构建钩子(Build Hooks)

VitePress 构建钩子允许你为网站添加新的功能与行为,典型用途包括:

  • Sitemap 生成
  • 搜索索引
  • PWA
  • Teleports(传送门内容处理)

buildEnd

  • 类型:(siteConfig: SiteConfig) => Awaitable<void>

buildEnd是构建 CLI 钩子,在构建(SSG)完成后、VitePress CLI 进程退出前运行:

export default { async buildEnd(siteConfig) { // ... } }

典型用途如生成 RSS feed(在UserConfig.buildEnd的 JSDoc 中明确举例,见 siteConfig.ts)。

postRender

  • 类型:(context: SSGContext) => Awaitable<SSGContext | void>

postRender是构建钩子,在 SSG 渲染完成后调用。它允许你在 SSG 期间处理 teleports 内容:

export default { async postRender(context) { // ... } }
interface SSGContext { content: string teleports?: Record<string, string> vpIcons: Set<string> [key: string]: any }

从类型定义看(types/shared.d.ts),SSGContext中的vpIcons是 SSR 期间通过useIcon注册的图标集合(完全限定名为collection:name),构建器据此只发出用到的图标样式。

transformHead

  • 类型:(context: TransformContext) => Awaitable<HeadConfig[]>

transformHead是为每个页面向<head>添加额外标签的构建钩子。它允许你添加无法静态写入 VitePress 配置的 head 条目。只需返回额外条目,它们会被自动与现有条目合并。

⚠️ 警告不要修改context内部的任何内容。

export default { async transformHead(context) { // ... } }
interface TransformContext { page: string // e.g. index.md (relative to srcDir) assets: string[] // all non-js/css assets as fully resolved public URL siteConfig: SiteConfig siteData: SiteData pageData: PageData title: string description: string head: HeadConfig[] content: string }

该钩子只在构建时调用,开发模式不会调用。额外标签会被加入构建生成的静态 HTML 文件,客户端导航时不会更新。

在很多情况下,使用transformPageData钩子是更干净的选择——该钩子同时作用于客户端导航与开发模式。但如果生成 head 标签计算开销较大,transformHead可以在开发阶段避免这一开销。

示例:添加og:imagemeta
export default { async transformHead(context) { if (context.page === '404.md') { return } // The implementation details of `generatePageImage` would depend // on your requirements. Here we assume it generates a suitable // image for each page and returns the image URL. const imageUrl = await generatePageImage(context) return [[ 'meta', { name: 'og:image', content: imageUrl } ]] } }

这里假设图片 URL 是动态生成且耗时的,使用transformHead可以在开发阶段避免该开销。对于更简单的场景,可以使用 frontmatter 的head设置,或transformPageData

transformHtml

  • 类型:(code: string, id: string, context: TransformContext) => Awaitable<string | void>

transformHtml是在每个页面内容写入磁盘之前对其进行转换的构建钩子:

⚠️ 警告不要修改context内部的任何内容。另外,修改 HTML 内容可能在运行时引起水合问题。

📝 注意此时图标样式表链接仍携带vp-icons.__VP_ICONS_HASH__.css占位符——内容哈希要等所有页面渲染完成才存在,紧接着才会被替换。内联或对 head 资源做指纹化的钩子应跳过该标签。

export default { async transformHtml(code, id, context) { // ... } }

transformPageData

  • 类型:(pageData: PageData, context: TransformPageContext) => Awaitable<Partial<PageData> | { [key: string]: any } | void>

transformPageData是转换每个页面pageData的钩子。你可以直接修改pageData,或返回变更后的值(会被合并进页面数据):

⚠️ 警告不要修改context内部的任何内容,并注意这可能会影响 dev server 的性能,尤其是钩子中有网络请求或重计算(如生成图片)时。可以通过process.env.NODE_ENV === 'production'做条件逻辑。

export default { async transformPageData(pageData, { siteConfig }) { pageData.contributors = await getPageContributors(pageData.relativePath) } // or return data to be merged async transformPageData(pageData, { siteConfig }) { return { contributors: await getPageContributors(pageData.relativePath) } } }
interface TransformPageContext { siteConfig: SiteConfig }

该钩子对 dev 与 build 都生效,且返回值会合并进pageData(两种写法等价)。TransformPageContext只包含siteConfig一个字段(见 siteConfig.ts)。

示例:添加<meta name="og:title">
export default { transformPageData(pageData) { const title = pageData.frontmatter.layout === 'home' ? 'VitePress' : `${pageData.title} | VitePress` pageData.frontmatter.head ??= [] pageData.frontmatter.head.push([ 'meta', { name: 'og:title', content: title } ]) } }
示例:添加 canonical 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 } ]) } }

延伸阅读

  • 完整的配置类型定义与 JSDoc:UserConfig/SiteConfig/TransformContext见 src/node/siteConfig.ts,HeadConfig/SSGContext/SiteData见 types/shared.d.ts;
  • 配置加载、归一化与目录级配置收集的实现见 src/node/config.ts,站点数据按路由解析与 head 合并逻辑见 src/shared/shared.ts;
  • 页面级覆盖规则见 Frontmatter 配置参考;
  • 多语言与 RTL 支持见 国际化指南,路由与重写见 路由指南,资源处理见 静态资源指南,部署时的 base 与相对构建见 部署指南。

【免费下载链接】vitepressVite & Vue powered static site generator.项目地址: https://gitcode.com/gh_mirrors/vi/vitepress

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询