Efficient LaTeX Rendering on the Web with Precompiled KaTeX
by Elias Hernandis • Published Feb. 7, 2023 • Tagged latex, web, workflow
There's quite a bit of math on this site. As most of us do, I write it using LaTeX which is a markup language1 where you write normal ASCII characters and after running it through some program you get nice looking math.
For instance, this
P(a < b \leq x) = \int_a^b f(x)\ dx
turns into this when compiled
Originally, there were LaTeX compilers designed to turn .tex
files into PDFs. The main use case was of course publishing papers and books, and those compilers are still probably the best option for typesetting, not just the math, but also the surrounding text.
However, PDFs are not very nice to look at on screens, especially if you're reading this on a small display which cannot fit a whole line without making it too small to read. So then people came up with ways of rendering LaTeX on the web.
A popular library is MathJax, which can run entirely on the client (i.e. the browser) and transforms LaTeX into pretty equations when the page is rendered. It requires loading a bunch of JavaScript and some heavy fonts. Don't get me wrong, what MathJax manages to do with just JS and some fonts is impressive compared to the average local TexLive (a popular LaTeX distribution) installation which takes around 2GB.
There are lighter weight, albeit less feature complete alternatives, like KaTeX which require less resources to run. But there's something even better: the MathML standard, a "low-level specification for mathematical and scientific content on the Web and beyond". It is pretty well supported in modern browsers which means if you write your equations in MathML you don't need to load a single external resource.
The only problem is that it's a bit verbose, since it's based on XML, has a strong focus on properly labeling everything and just was not designed to be written by hand. For instance the equation would look like this if written in MathML3
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE math PUBLIC "-//W3C//DTD MathML 2.0//EN"
"http://www.w3.org/Math/DTD/mathml2/mathml2.dtd">
<math xmlns="http://www.w3.org/1998/Math/MathML">
<mrow>
<mi>a</mi> <mo>⁢</mo> <msup><mi>x</mi><mn>2</mn></msup>
<mo>+</mo><mi>b</mi><mo>⁢</mo><mi>x</mi>
<mo>+</mo><mi>c</mi>
</mrow>
</math>
Nowadays, what libraries like MathJax and KaTeX do is convert LaTeX into MathML and load the standard TeX fonts so that it looks exactly like it was produced by one of the original compilers. As I mentioned earlier, the default mode for these libraries is to do this conversion on the browser every single time a user loads the page!
But of course we can do this on the server once after updating the content and then just send the MathML inside our HTML page and include a <link>
to the relevant style sheet which will load the font. Even better, if we're just publishing static pages, we can do this once when we're done editing, compile the site and upload it to any hosting provider.
This is requires transmitting less information over the wire and less redundant computation, which makes it not only a faster alternative but also far more environmentally friendly!
How I render math on this site
I recently moved from Jekyll (a static site generator) to something more of a CMS which would allow me to edit and write from the browser without having to compile and upload the site.4
I write in Markdown, more precisely a flavor of GitHub Flavored Markdown which includes syntax for math. Inline math is encoded between dollar-signs and back ticks2 and block math is written as a code block with the math
language.
Then I use python-markdown
with the markdown_katex
extension to convert that math to MathML. It also takes care of automatically adding the <link>
tag to the KaTeX style sheet just for posts that need it.
This means that saving a post takes a bit more time (like 1-2 seconds for one of the posts linked at the start of the article) but in exchange you're able to load any page on this site in like 200ms or so!
I'm very happy with the results so far, I've not encountered any math that I'm unable to render with the excellent KaTeX (admittedly I don't do fancy stuff with commutative diagrams or weird symbols so ymmv). It even works on the RSS feed (at least if you read it using Thunderbird)!
These are the kinds of solutions that I love the most: making things extremely fast by avoiding doing work more times than necessary, building on top of well established technologies, open standards like MathML and great open-source projects like KaTeX. If you're interested, that's the kind of work that we do every day at Negative Epsilon, a tech and math consulting company that I co-founded with some of the most talented people I know more than three years ago. Do contact me if you think we could work together!
-
LaTeX is one of the earliest markup languages out there and comes from the even older TeX, dating all the way back to 1978. The story behind TeX is fascinating, it was written by Donald Knuth because he found out there was no good-enough typesetting system on which he could write his masterpiece The Art of Computer Programming. TeX or LaTeX are now used by millions of academics every day to encode the worlds knowledge with an open standard that produces visually stunning results. ↩
-
I had to give up trying to write the sequence back-tick, dollar, back-tick, back-tick in Markdown without messing up the whole page after 10 minutes of trying, but you get the idea. ↩
-
This example is from the Wikipedia page on MathML. ↩
-
I'm very sad to move away from Jekyll, it's worked wonders over the last 7 years with this site and was the last thing that made me go back to Ruby once in a while (even if it was just as a user). ↩