MathJax与KaTex的对比与选型
一、背景
有道小P(小P官网 )是新一代AI全科学习助手,通过拍题答疑、AI查词和翻译等工具提升学习能力,提供用户在学习或者工作中,不同细分场景下需求的解决。
该项目中涉及到流式回答中公式的渲染。目前主流的公式语言是LaTex、TEX、MathML与AsciiMath四种。在项目中,我们用到的是LaTex公式。
二、公式语言介绍
LaTeX、TeX、MathML 和 AsciiMath 都是与文档排版和数学公式表示相关的技术,但它们各自有不同的用途和特点:
1. LaTeX (LAh-TEK or LAY-tek):
- LaTeX 是一种基于 TeX 的排版系统,由 Leslie Lamport 于1985年开发。
- 它提供了一套丰富的宏包和文档类,使得用户可以方便地创建具有复杂排版需求的文档,如学术论文、书籍和技术报告。
- LaTeX 特别适合数学、物理和计算机科学等领域的文档排版,因为它具有强大的数学公式排版能力。
2. TeX (TEKH):
- TeX 是由 Donald E. Knuth 开发的一种排版系统,最初设计用于生成高质量的数学和科学文献。
- 它是一种编程语言,具有强大的排版功能,包括宏定义和自动化排版特性。
- TeX 是 LaTeX 和其他许多排版系统的基础。
3. MathML (Math Markup Language):
- MathML 是一种基于 XML 的标记语言,用于在互联网上表示数学公式和符号。
- 它被设计为与其他 XML 技术一起使用,并可以被浏览器和其他软件解析以显示数学内容。
- MathML 支持复杂的数学表达式,并可以用于创建可访问的数学内容。
4. AsciiMath:
- AsciiMath 是一种轻量级的数学标记语言,使用简单的 ASCII 字符来表示数学公式。
- 它易于编写和阅读,适合在不支持 LaTeX 或 MathML 的环境中使用,如电子邮件、论坛帖子或简单的文本编辑器。
- AsciiMath 可以被特定的软件或服务转换为 LaTeX 或 MathML,以便进一步处理和显示。
5. 小结
- LaTeX 和 TeX 主要用于创建具有高质量排版的复杂文档,特别是在学术领域。
- MathML 提供了一种在互联网上表示数学内容的标准方式,支持复杂的数学表达式和可访问性。
- AsciiMath 是一种简单易用的数学标记方法,适用于快速的文本交流和笔记。
- 每种技术都有其适用场景,选择哪一种取决于具体的需求、目标受众和期望的排版质量。
三、LaTex的一些基础用法介绍
可将公式复制到这里实时查看渲染效果
1. 数学表达式
$\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}$
$E = mc^2$。
2. 希腊字母
$\alpha, \beta, \gamma, \delta, \epsilon$
3. 数学符号
$\sum, \prod, \lim, \infty, \triangle, \pm, \times, \div, \neq$
4. 上标和下标
x_i 表示第 \(i\) 个 \(x\) 的值。 $f(x) = ax^2 + bx + c$
5. 括号与矩阵
- 括号:
$\left( \frac{a}{b} \right)$
- 矩阵:
\begin{matrix}
a & b \\
c & d
\end{matrix}
6. 运算符
$\frac{a}{b}, \sqrt{a}, \overline{AB}, \underline{AB}, \oint, \bigcap, \bigcup$
7. 分数与根号
$\frac{1}{2}, \dfrac{\partial f}{\partial x}$ ,$\sqrt{2}, \sqrt[3]{x}$
8. 渲染效果

四、主流工具MathJax
与KaTex
的对比
1. 体量不同
- KaTeX 仅仅支持关于 TeX/LaTeX 输入和 HTML、MathMl 的输出,更加轻量化,不会支持Latex的所有功能,特别是一些高级宏包和命令
- MathJax更加综合,还支持 MathML 和 AsciiMath 的输入,且输出格式还支持 svg、mathML,还提供了对辅助技术的支持(例如,为数学生成语音文本,或为它输出盲文,并提供数学的交互式探索,等等)
2. 渲染速度不同
- KaTex 以其快速渲染而闻名,它通常比 MathJax 快得多,因为它使用纯 JavaScript 来生成和渲染数学公式,而不是像 MathJax 那样使用 HTML+CSS 或者 SVG。
- MathJax 相对会更慢,因为:
- 使用 MathML 作为其内部格式,因此所有输入格式都被转换为MathML ,输出时候再转成配置的格式如 SVG,这使得耗费的时间更多
- 渲染时追踪更多的边界信息如高度、深度、宽度和扩展等,来保证正确处理SVG输出以及MathJax的缩放特性
- MathJax
- 需要注意的是,MathJax3 是对mathjax2版本的重写,在性能上有了很大的提升,且支持通过单文件配置,两者的速度差已经明显缩小了
3. 支持的语法范围不同。
MathJax
可支持更多的语法,如下面的公式,在katex中并不支持,而mathjax中可渲染:
K\kern-.2em\raise.21em{\scriptstyle{A}}\kern-.17em T\kern-.14em\lower.5ex{E}\kern-.115em X
- mathjax渲染结果:
- KaTex中无法渲染
此外,KaTex 也不支持 \label
等语法,e.g:
\begin{equation}
\frac{\partial^2 u}{\partial t^2} - c^2 \nabla^2 u = 0
\label{wave_eq}
\end{equation}
% 为公式设置一个自定义标签并显示公式
\begin{equation}
\left( \frac{\partial^2}{\partial x^2} - \frac{\partial^2}{\partial y^2} \right) \psi = m^2 \psi
\tag{S}
\label{sch_eq}
\end{equation}
4. 扩展依赖支持程度不同
- MathJax有更丰富的扩展包,如physics.js,使得可以支持更丰富的物理公式(
e.g. \pderivative{x}
) - 对比之下 KaTex 则相对有限
5. 浏览器的兼容性
- KaTeX 相对是更新的工具,因此对旧版本浏览器兼容较差,但在各种浏览器上的性能表现相对一致。
- MathJax 支持更广泛的浏览器,包括一些旧版本,但不同浏览器的性能可能会有所不同。
6. 社区和支持:
- KaTeX 作为一个相对较新的项目,KaTeX 的社区可能没有 MathJax 的社区那么成熟。
- MathJax 由于存在时间较长,MathJax 拥有一个成熟的社区和大量的用户基础,提供了大量的教程、问答和第三方资源。
7. 小结
综上,KaTex与MathJax各有优劣,综合考虑到如下几个因素,我们在项目中最终使用了 MathJax中的Tex2Svg形式
- 历史原因:代码是从其他项目迁移,用的mathjax 2.7.6版本,改成 KaTex 会有一定成本
- 场景为h5应用,基本不会出现同时渲染大量公式,渲染速度的差异可以忽略
- 流式输出公式内容有较大不确定性,因此需要支持更丰富的MathJax
- 体积问题。MathJax 2版本,需要上百M,这是MathJax的劣势,但是在MathJax新版本这个问题并不存在了
五、MathJax的版本对比与升级
1. 版本升级背景
目前主流的是Mathjax 2
与Mathjax 3
版本,Mathjax 4
仍处于beta版本
有道小P的前端代码是从有道硬件中拉的,用的是mathjax2.7.6版本,压缩前体积有150M,并有数万个小文件。
在ios中,解压后的文件最低占用4.1KB,导致第一版,在ios应用市场上体积去到了300+M。
2. 产生原因
- mathjax2的使用中,先加载入口文件mathjax/mathjax.js?xxx,再根据实际要展示的内容,加载其他需要的资源文件,实际依赖是不确定的
- 可以拷贝这份html,修改里面的latex公式后,加载的js文件会有所不同 因此,mathjax2中,哪怕我只需要tex2svg的内容,其他形式的转换并不需要,最稳妥的方法也是将整个文件夹拷贝下来,避免渲染时丢失文件
当然,mathjax2拷贝下来的一些没配置的文件是可以直接删除的: 1.字体文件、其它的的转换方法文件等
- 项目中只需要支持latex公式,因此用于支持mathMl、AsciiMath格式的文件也可以直接删掉 在这之后上,难以确定哪些文件是完全不需要的。删除后,仍有近100M的体积
3. MathJax2与3版本的对比
mathjax3与mathjax2主要有有下列区别:
- 利
- mathjax3重构了2,渲染流程
- 渲染性能优化,特别是在启动时间上,因为采用了新的架构,此外,mathjax2是较早的版本,涉及到IE浏览器等兼容场景,而3并没有
- 实现了组件,对不同的转换方式抽离成了单独的文件,配置更灵活
- 有效解决了使用时不存在依赖不确定的问题
- 体积更小 -小很多那种小!
- 一些需要在mathjax2中额外配置的扩展,在3中是默认加载的
- 弊
- api与配置的变化、兼容性等,需要重新配置效果
- mathjax3移除了一些配置
- mathjax3并没有完全移植2的内容,因为还在迭代中,如扩展autobold等
- mathjax2的HTML-CSS配置中支持STIX与TEX字体,3仅支持TEX字体
- mathajx3不支持自动换行 综上分析,升级到mathjax3虽然也有弊,但是影响都不大,体积优化上利大于弊
4. 升级实践
- 配置调整:利用官方转换工具得到转换后的配置以及注意事项
- 插件扩展: a. 小P项目中,mathajax2使用了如下插件,这些插件都需要额外加载,并在加载成功后重新注入到mathjax中 + ["AMSmath.js","AMSsymbols.js","extpfeil.js","mhchem.js", "autobold.js", "enclose.js", "color.js"] + 上述依赖除不被支持的autobold外,都已经内置到mathjax3中的tex-svg.js文件中,因此不再需要显式引入 b. 将2中显式引入插件的相关代码删除,因为3中被自动引入了
- 渲染的写法变了,变成了promise,而不是mathjax2中的callback
const rendMath = (mathEle, callback) => {
const mathContent = mathEle || document.body;
if (window.MathJax) {
// 使用MathJax.typesetPromise进行异步渲染
window.MathJax.typesetPromise([mathContent]).then(() => {
// 类型设置完成后,执行回调函数
if (callback) {
callback();
}
}).catch((error) => {
console.error('MathJax typesetting failed:', error);
});
}
}
5. 升级效果
mathjax2 升级为 mathjax3 后
- 同样是tex2svg的功能,mathjax3只需要几百KB,mathjax2在稳妥的情况下则需要100+MB,体积减少了99%
- 渲染速度更快
- 引入的文件从数万个文件变成一个
六、升级mathjax3后的异常与解决
公式无法自动换行
在升级mathjax3后,发现出现了公式过长时,无法自动换行的问题(Mathjax2没有这个问题)
这是由于mathjax3没有完全迁移mathjax2,因此不支持。
豆包的公式渲染使用的是mathjax3.2.2,一样有这个问题,如下图:
换行问题解决方案
升级至mathjax4。 通过github issue可知,在mathajx4-beta版本已经实现了换行内容
升至mathjax4后的适配
mathjax4的改动内容见文档,对使用中有影响的主要是下面三个
1. 增加自动换行属性,可以这样配置:
MathJax = {
svg:{
linebreaks: { // options for when overflow is linebreak
inline: true, // true for browser-based breaking of inline equations
width: '100%', // a fixed size or a percentage of the container width
lineleading: .2, // the default lineleading in em units
LinebreakVisitor: null, // The LinebreakVisitor to use
}
}
}
2. 修改了默认字体,且增加了可使用的字体(mathjax3只支持一种字体),可通过下列属性配置
MathJax = {
...
output:{
font:'mathjax-tex'
}
...
}
3. 点击公式和有较大概率出现弹窗
检查发现是因为4默认启用了无障碍功能,会显示公式字符与盲文(mathjax3也启用了,但点击后不会有弹窗,4会有)
a. 点击公式字母后的弹窗示意图
b. 调用的位置(浏览器中调试后定位到)\
c. 解决:关闭无障碍配置,因为项目中不考虑该场景(无障碍配置文档:docs.mathjax.org/en/latest/o…)
MathJax = {
...
options: {
a11y: {
speech: false, // switch on speech output
braille: false, // switch on Braille output
subtitles: false, // show speech as a subtitle
viewBraille: false, // display Braille output as subtitles
}
}
...
};
前面提到,mathjax4处于beta版本,但是实际上该版本已经迭代了两年了,相对比较稳滴,且升级后经测试暂未发现渲染异常的情况
七、 其他流式对话的公式渲染工具
Kimi
: KaTex
豆包
: MathJax 3.2.2
转载自:https://juejin.cn/post/7397638569732456488