数式をSVG化することで表示速度を12倍高速化した

以前、 Markdownをはてな記法にパースする - あおいろメモで、数式を含む記事をはてなブログに快適に投稿できる環境を整えましたが、課題がありました。

MathJaxがクソ重い

MathJaxはJavaScriptでクライアントサイドで本文中の TeX フォーマットを探して全部 SVG に置き換える処理をしています。(参考:サーバーサイド MathJax で数式表示を高速化する | tech - 氾濫原)。なので数式がたくさんある記事をスマホで開こうとするとJavaScriptがフリーズしてしまい見れたものではありませんでした。

スマホのPageSpeedスコア

これは1次元のトンネル効果の導出 - あおいろメモPageSpeedスコアです。ひどいスコアです。自分が持っているスマホ(Galaxy S8)でも読み込みに90秒近くかかり、しかも読み込んだ後もスクロールがガクガクでとてもじゃないけど見れたものではありませんでした。

そこで、あらかじめTeX数式をSVG化してサイトに埋め込んでしまえば、高速化できるのではないかと考え、MarkdownをHTML化し、Markdown中のTeX数式はSVG化するdockerコンテナ群を作りました。

GitHub - SolKul/md_to_html: Convert Markdown to HTML and TeX to SVG

使い方

その1. コンテナを立ち上げます

$ docker-compose up -d

その2. converterコンテナでbashを起動します

$ docker-compose exec converter /bin/bash

その3. converterコンテナ内で main.py を実行します

$ python main.py

python_src内のSample.mdSample.htmlに変換されます

実装

converter と、 node_svgという名前の2つのコンテナを使っています。

converterコンテナにはPython環境が乗っており、Markdown書式をHTMLに変換する自作モジュール、md_pareserを使って、TeX数式以外のMarkdownをHTMLに変換します。自作モジュール内では Python-Markdownというモジュールを使っています。TeX数式については次のnode_svgコンテナにpostで投げてSVGに変換してもらいます。

node_svgコンテナはnode.js環境が乗っており、TeX数式をSVGに変換します。mathjax-nodeモジュールを使っています。

効果

SVG化後のPageSpeedスコア

数式をSVG化した所、PageSpeedスコアは若干改善しました。(まだまだ悪いですが)

また、手元の環境でも、改善前はページのロード時間が

だったのが、SVG化によって

スマホに関しては12倍高速化できました。PageSpeedスコアはまだまだ低いですが、これなら許容範囲です。

課題

  • dockerを使うのではなく、単純なPythonモジュールにできなかったのか
  • コンテナを1つにまとめられるのではないか
  • ホストとの共有ボリュームにPythonのソースを置くのは良くない気がする
  • ホストとの共有ボリュームに.mdファイルを置いて変換するのも良くない
  • 記事中にSVGを含むため、文字数が多くなりすぎてはてなブログのプレビューが重くなって使えなくなった
  • 記事の容量が大きくなりすぎて、記事が投稿できない場合がある

もうちょっときれいな実装がありそうですが、自分のスキル不足で汚い実装となってしまったのが悔やまれます。

似たようなこと

作ってから気づいたけど似たようなことやってる人たくさんいましたね(汗

LaTeX の数式を PNG と SVG に変換するスクリプト - akihiko’s tech note

LaTeXの数式をpngに変換する: dvipngを使う | ゴルディアスの涙目

(あとrender.githubusercontentにURLエンコードしたTeX数式を投げている人もいますけど、勝手にGitHubのサービスを他の用途に使ってもいいのでしょうか?)