数式をSVG化することで表示速度を12倍高速化した
以前、 Markdownをはてな記法にパースする - あおいろメモで、数式を含む記事をはてなブログに快適に投稿できる環境を整えましたが、課題がありました。
MathJaxがクソ重い
MathJaxはJavaScriptでクライアントサイドで本文中の TeX フォーマットを探して全部 SVG に置き換える処理をしています。(参考:サーバーサイド MathJax で数式表示を高速化する | tech - 氾濫原)。なので数式がたくさんある記事をスマホで開こうとするとJavaScriptがフリーズしてしまい見れたものではありませんでした。
これは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.md
がSample.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化によって
とスマホに関しては12倍高速化できました。PageSpeedスコアはまだまだ低いですが、これなら許容範囲です。
課題
docker
を使うのではなく、単純なPythonモジュールにできなかったのか- コンテナを1つにまとめられるのではないか
- ホストとの共有ボリュームにPythonのソースを置くのは良くない気がする
- ホストとの共有ボリュームに
.md
ファイルを置いて変換するのも良くない - 記事中にSVGを含むため、文字数が多くなりすぎてはてなブログのプレビューが重くなって使えなくなった
- 記事の容量が大きくなりすぎて、記事が投稿できない場合がある
もうちょっときれいな実装がありそうですが、自分のスキル不足で汚い実装となってしまったのが悔やまれます。
似たようなこと
作ってから気づいたけど似たようなことやってる人たくさんいましたね(汗
LaTeX の数式を PNG と SVG に変換するスクリプト - akihiko’s tech note
LaTeXの数式をpngに変換する: dvipngを使う | ゴルディアスの涙目
(あとrender.githubusercontent
にURLエンコードしたTeX数式を投げている人もいますけど、勝手にGitHubのサービスを他の用途に使ってもいいのでしょうか?)