Speed up MathJax slow loading time

MathJax user Fei Wang asked in the forum thread mathjax rendering is taking too much time about a huge page that was taking too long to load.

I had a look at it for him and came up with the following suggestions.

Original page (7 MB, > 30 s)

WARNING: huge page Here's a copy - don't be surprised if it doesn't work) was over 7 MB and it took around 30 seconds to load, process and become responsive. This is way too long for most users who will assume the page has frozen.

The page was developed using Jupyter Notebook, which is a Python-based tool that can output HTML. Trouble is, this HTML is often not valid, and nearly always very bloated.

The page has a huge amount of external CSS and JS (most of which I've removed from my copy since it would have been broken), and this badly blocks the loading and subsequent processing of the page.

First suggestion - reduce bloat and use MathJax lazy load (6 MB, TTI: ~21 s)

I removed almost all of the superfluous styles and scripts on the page, and set MathJax to "lazy load", so it would only process math as the user scrolled down the page (rather than trying to process the whole page, which took a long time.)

Here's the Revised page

The actual page size is now around 6 MB, and the amount of external bloat is almost zero, except for the MathJax scripts.

It's a lot quicker (now "time to interactive" is 6 seconds, rather than 30) but it still can be improved.

Second suggestion - minimise (300 kB, TTI: ~1 s)

There were several SVGs on the page. Normally they are quite small, but in this case they are the output produced by Jupyter Notebook and they were so bloated they were almost impossible to fix. So I took screenshots of them and saved them as WEBPs.

The file size for the page has gone down from 6,270 kB to 300 kB, a reduction of 95.2%. The number of HTML elements (a key reason the original page is so slow) has gone down from 88,000 elements to 10,000 (a reduction of 89%), before MathJax starts its processing.

"Time to interactive" (when the user can actually start scrolling the page) has gone down from 21 s to under 1 second.

Here's the minimised version.

Third suggestion - AJAX (8 kB, TTI: ~0.370 ms)

We could always break up a huge page into several smaller pages, but sometimes we want the whole thing to appear together.

This next version loads just a small part of the page initially, then as the user scrolls down, it extracts the rest of the page in discrete slabs, (similar to the way Twitter, Facebook and TikTok have a "infiniste scroll").

We now have a file size on load of just 8 kB and the number of DOM elements is just 600 (before MathJax adds its new elements).

"Time to interactive" is now just 0.370 s.

Here's the AJAX version.

For each of these faster examples, I'm using lazy loading for both images and for MathJax. Both the "MIN" and "AJAX" pages load quickly on a phone and scrolling is smooth.

Speed analysis

The GTMetrix analyses for the original and the 3 revised pages show dramatic improvements in speed. (Such analyses expire after a time, so links are not included here.)