Math rendering engines and loading strategies
Math rendering engines and loading strategies
Historical evaluation — reviewed against Valaxy 1.0 on 2026-10-04
This article preserves the 2026-02-23 engine evaluation. Its configuration examples remain relevant, with these updates for Valaxy 1.0:
- Critical CSS inlining has been removed. SSG does not imply inline CSS or zero stylesheet requests; styling uses build assets and the FOUC guard.
features.katex: falsedisables KaTeX rendering by default, but an individual page can enable it withkatex: true. Unless MathJax is enabled, the KaTeX plugin and styles remain available for that override.math: trueselects MathJax and takes precedence over KaTeX. Valaxy also registers KaTeX’s mhchem extension for chemical notation.- Sizes and performance comparisons below are historical observations, not measurements or guarantees for 1.0. Measure the current dependency versions and your site’s HTML, styles, and fonts together.
See math configuration, examples, and the SSG migration guide.
背景
Valaxy 需要支持 Markdown 中的数学公式渲染。此前仅支持 KaTeX,VitePress 则选择了 MathJax3。本文评估两种引擎的优劣,以及 KaTeX 的加载策略。
KaTeX vs MathJax3 对比
渲染性能
| 维度 | KaTeX | MathJax3 |
|---|---|---|
| 渲染速度 | 极快(专为速度优化) | 较慢(功能更全面) |
| 渲染位置 | Node 端构建时渲染为 HTML | Node 端构建时渲染为 SVG |
| 客户端 JS | 零(构建时已渲染完成) | 零(构建时已渲染完成) |
两者在 Valaxy 中都是构建时渲染,不依赖客户端 JS,因此运行时性能差异不大。
输出格式与依赖
| 维度 | KaTeX | MathJax3 |
|---|---|---|
| 输出格式 | HTML + CSS spans | SVG(自包含矢量图) |
| 外部 CSS | 需要 katex.min.css(~1.2KB gzip) | 无 |
| 字体文件 | ~20 个 woff2(浏览器按需加载) | 无(SVG 内嵌字形) |
| FOUC 风险 | CSS 未加载前有闪烁风险 | 无(SVG 自包含) |
| 按需特性 | 需要全局加载 CSS | 天然按需——无公式页面零开销 |
功能完整性
| 维度 | KaTeX | MathJax3 |
|---|---|---|
| LaTeX 覆盖度 | 大部分常用命令 | 更全面,支持更多扩展 |
| 交换图/XyJax | 不支持 | 支持(通过 XyJax-v3) |
\ce{} 化学 | Valaxy 已注册 mhchem 扩展 | 内置支持 |
\cancel/\xcancel | 支持 | 支持 |
| 自定义宏 | 支持 | 支持(更灵活) |
| 可访问性 | MathML 输出 | MathML + SVG |
依赖体积(npm 包大小)
| KaTeX | MathJax3 (markdown-it-mathjax3) | |
|---|---|---|
| 安装大小 | katex: ~3.5MB(含字体) | markdown-it-mathjax3@4: ~40MB(mathjax-full) |
| 客户端影响 | ~1.2KB CSS(gzip) | 零 |
MathJax 的 npm 安装体积更大,但这仅影响
node_modules,不影响客户端产物。
为什么 VitePress 选择 MathJax3?
- 零运行时依赖:SVG 内联在 HTML 中,无需 CSS/字体/JS
- 天然按需:无公式页面完全零开销
- 通用文档工具:大多数文档站不使用数学公式,MathJax 的 SVG 方案确保零影响
math: false默认关闭:仅需要时才安装和启用
Valaxy 的选择:KaTeX + MathJax 分离配置
Valaxy 通过两个独立配置分别控制两种引擎,语义清晰,对齐 VitePress:
// valaxy.config.ts
// KaTeX(默认开启)
export default defineValaxyConfig({
features: { katex: true },
})
// MathJax3(对齐 VitePress,零 CSS 依赖)
// 需先安装:pnpm add markdown-it-mathjax3
export default defineValaxyConfig({
math: true,
})
// 默认不渲染公式;单篇仍可通过 frontmatter.katex: true 开启
export default defineValaxyConfig({
features: { katex: false },
})features.katex— 控制 KaTeX(Valaxy 原有配置,保持不变)math— 控制 MathJax(对齐 VitePressmarkdown.math)- 两者互斥:启用
math时 KaTeX 自动禁用
KaTeX 加载策略评估
前提
当选择 KaTeX 引擎时,首页首屏不需要渲染数学公式,但 katex.min.css(~25KB)及字体文件会在所有页面全局加载。评估是否应改为按需加载。
方案对比
方案 A:全局条件加载(当前方案)
在 virtual/styles.ts 中,未启用 MathJax 时全局引入 katex.min.css + katex.scss,以支持默认渲染和单篇 katex 覆盖。
方案 B:按需加载
从全局样式移除 KaTeX CSS,通过 node 端正则检测文章内容中的数学公式语法、客户端 DOM 检测 .katex 元素,按需动态 import() CSS。
对比
| 维度 | 全局加载 | 按需加载 |
|---|---|---|
| 首屏性能 | ~1.2KB gzip CSS | 无数学页面零开销 |
| 实现复杂度 | 一行 import | node 检测 + composable + DOM 检测,分布 5+ 文件 |
| 可靠性 | 不可能遗漏 | 依赖正则和 DOM 检测的完备性 |
| FOUC 风险 | 无 | 列表页 DOM 检测路径存在短暂 FOUC |
| SSG 友好度 | 完美 | 文章详情页 OK;列表页 onMounted 路径不参与 SSR |
| 维护成本 | 低 | 中——多处代码联动,正则需持续维护 |
按需加载方案的具体问题
1. 正则检测误判与遗漏(严重)
const hasInlineMath = /(?<![\\$])\$(?!\$)(?!\s).+?(?<!\s)\$(?!\$)/s.test(content)
const hasBlockMath = /\$\$[\s\S]+?\$\$/.test(content)- 误判:代码块中的
$(如$HOME)、金额$100会被误匹配 - 遗漏:
\( ... \)、\[ ... \]、\begin{equation}等 LaTeX 语法未检测
2. 列表页摘要的 FOUC(中等)
文章列表页通过 v-html 渲染含 KaTeX 的 excerpt。DOM 检测在 onMounted 后执行,CSS 动态 import() 存在加载延迟,导致公式短暂以无样式原始文本呈现。
3. SSR 模块级状态(中等)
loaded 变量为模块级别,SSR 中跨请求共享,可能导致部分页面的 CSS 未被 Vite 正确收集。
4. 覆盖范围不完整
列表页、摘要组件(YunPostCard、PressArticleCard)不经过 ValaxyMd.vue,需要额外的全局 DOM 检测兜底。
关键认知
KaTeX CSS 的实际成本被高估了:
katex.min.css原始 ~25KB,但 gzip 后仅 ~1.2KB(大量重复的@font-face声明压缩率极高)- 字体文件由浏览器天然按需加载——只有页面实际渲染了对应
@font-face的元素才会下载字体,不使用 KaTeX 的页面不会下载任何字体文件 - 当时记录的 CSS 压缩体积约为 1.2KB gzip,不含字体和其他资源。当前请求数量与体积应以实际构建产物为准。
KaTeX 加载结论
KaTeX 引擎保持全局条件加载,理由:
- 1.2KB 的 CSS 开销对首屏性能影响可忽略不计
- 按需加载引入的工程复杂度、FOUC 风险、正则维护成本远超其收益
- 博客场景下技术文章普遍使用数学公式,按需加载的实际收益有限
- 样式统一交给构建产物加载;Valaxy 1.0 已移除 Critical CSS 内联,不能再以 SSG 推断没有额外 CSS 请求。
如果需要零 CSS 开销,推荐切换到 MathJax math: true,从架构层面彻底消除外部 CSS/字体依赖。
总结
| KaTeX | MathJax3 | |
|---|---|---|
| 适用场景 | 简单公式、追求极速渲染 | 复杂 LaTeX、需要零客户端依赖 |
| 推荐人群 | 大多数博客作者(默认) | 学术写作、重度数学用户 |
| 客户端开销 | ~1.2KB CSS | 零 |
| 配置 | features: { katex: true } | math: true |
To Be Continued.