VitePress 集成 Mermaid 插件、dayjs 导出错误与 pnpm 依赖冲突
VitePress 进阶实战:深度解决 Mermaid 插件嵌套、dayjs 导出错误与 pnpm 依赖冲突
前言
在搭建个人技术博客时,我选择了 VitePress 作为静态站点生成器。为了实现侧边栏自动生成和 Mermaid 图表支持,我引入了 vitepress-sidebar 和 vitepress-plugin-mermaid。然而,在插件嵌套的过程中,我遭遇了从“语法高亮失效”到“浏览器一片空白”的一系列深度坑位。本文将记录这一系列问题的排查与最终解决方案。
核心痛点与错误复现
1. 致命的“空白页”:dayjs 导出错误
在引入插件并尝试启动服务后,浏览器控制台报错:
Uncaught SyntaxError: The requested module '...dayjs.min.js' does not provide an export named 'default'
原因分析:vitepress-sidebar 内部依赖 dayjs 处理文件日期。由于 dayjs 是 CommonJS 模块,而 Vite 运行在 ESM 环境下,在复杂的插件嵌套(withMermaid 包裹 withSidebar)中,Vite 的自动转换机制失效,导致无法识别默认导出。
2. 构建崩溃:Vue 标签解析错误
SyntaxError: Element is missing end tag. (16:24)
原因分析:VitePress 会将 Markdown 解析为 Vue 组件。如果在正文中书写了包含尖括号的类名(如 <SqlSessionFactory>)且未被代码块包裹,编译器会将其误认为未闭合的 HTML 标签。
3. pnpm 依赖隔离:无法解析依赖
Failed to resolve dependency: dayjs, mermaid, debug...
原因分析:使用 pnpm 时,依赖被严格隔离在各自的软链接中。Vite 的 optimizeDeps 尝试在根目录预构建这些插件的内部依赖时,因为根目录 node_modules 找不到它们而报错。
最终解决方案:全栈配置模板
通过多次调试,我总结出一套“插件嵌套 + 依赖提升 + Vite 修正”的组合拳。
第一步:显式安装“隐身”依赖
针对 pnpm 找不到依赖的问题,最直接的办法是将插件的内部依赖手动提升到根目录。
pnpm add dayjs mermaid @braintree/sanitize-url debug cytoscape cytoscape-cose-bilkent -D
第二步:深度修正 config.mts 配置
关键点在于:将 markdown 配置移至顶层,并利用 vite.optimizeDeps 强制转换模块格式。
import { defineConfig } from 'vitepress';
import { withSidebar } from 'vitepress-sidebar';
import { withMermaid } from 'vitepress-plugin-mermaid';
const vitePressConfig = {
// 1. 顶层配置:解决 Shiki 语言加载问题
markdown: {
languages: ['java', 'sql', 'xml', 'yaml', 'asm', 'redis'],
theme: 'vitesse-dark',
lineNumbers: true
},
// 2. 核心修复:解决 dayjs 导出与依赖预构建
vite: {
optimizeDeps: {
include: ['dayjs', 'mermaid', '@braintree/sanitize-url', 'debug', 'cytoscape']
},
build: {
commonjsOptions: {
include: [/dayjs/, /node_modules/] // 强制转换 CJS 模块
}
}
},
themeConfig: {
nav: [
{ text: 'AI', link: '/AI/' },
{ text: '数据', link: '/数据/' }
],
outline: { level: [2, 6], label: '页面导航' }, //
search: { provider: 'local' } //
}
};
// 3. 插件嵌套:Mermaid 包裹 Sidebar
export default withMermaid(
withSidebar(vitePressConfig as any, [
{ scanStartPath: 'AI', resolvePath: '/AI/', collapsed: true },
{ scanStartPath: '数据', resolvePath: '/数据/', collapsed: true }
])
);
第三步:清理缓存(救命良药)
每次修改完插件逻辑或依赖后,必须执行清理操作,否则旧的错误 ES Module 缓存会持续干扰。
# 删除 Vite 预构建缓存
rm -rf node_modules/.vite
# 删除 VitePress 运行缓存
rm -rf .vitepress/cache
避坑
- 反引号包裹一切技术名词:在 Markdown 中,任何包含
<>的代码片段(即使是类名)都必须放在 ` 内,防止 Vue 编译器解析报错。 - 配置层级敏感:VitePress 的
markdown配置绝不能写在themeConfig里,否则所有自定义语言高亮都会失效。 - 重视 pnpm 报错:当看到
Failed to resolve dependency时,不要犹豫,直接pnpm add该依赖到开发环境。 - 插件嵌套顺序:经验证,
withMermaid(withSidebar(config))是目前最稳定的写法。
浙公网安备 33010602011771号