Docusaurusで数式をクライアントサイドレンダリング(CSR)する
Docusaurusは静的サイトジェネレータなので、すべてのページがビルド時にレンダリングされます.
DocusaurusのマークダウンからHTMLにレンダリングする部分 は remark と rehype が処理しています.数式を有効にするには、Docusaurusのドキュメント によれば、remark-math
と rehype-katex
(または rehype-mathjax
)を使います.
しかし、2,3個の数式ならともかく、それなりの数があるとビルドに時間がかかるようになり、生成されるhtmlやjsファイルが肥大化します.もちろん、数式も含めて事前にレンダリングするので、閲覧する場合はブラウザで数式の処理が入らず高速に表示できますが、個人的にはデメリットの方が大きいので、数式処理はクライアントサイドでしたいところです.ここでは、その方法を記録しておきます.
必要なスクリプトやCSSファイルを読み込む
今回は katex を使って数式処理をします.バージョンは 0.16.4
です.
必要なファイルは以下の通りです.
- //cdn.jsdelivr.net/npm/katex@0.16.4/dist/katex.min.css
- //cdn.jsdelivr.net/npm/katex@0.16.4/dist/katex.min.js
- //cdn.jsdelivr.net/npm/katex@0.16.4/dist/contrib/auto-render.min.js
Docusaurusでこれらを読み込むようにするには docusaurus.config.js
の scripts
および stylesheets
で指定します.
const config = {
scripts: [
{
src: "https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/katex.min.js",
integrity: "sha384-PwRUT/YqbnEjkZO0zZxNqcxACrXe+j766U2amXcgMg5457rve2Y7I6ZJSm2A0mS4",
crossorigin: "anonymous",
defer: true,
},
{
src: "https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/contrib/auto-render.min.js",
integrity: "sha384-+VBxd3r6XgURycqtZ117nYw44OOcIax56Z4dCRWbxyPt0Koah1uHoK0o4+/RRE05",
crossorigin: "anonymous",
defer: true,
}
],
stylesheets: [
{
href: 'https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/katex.min.css',
type: 'text/css',
integrity: 'sha384-vKruj+a13U8yHIkAyGgK1J3ArTLzrFGBbBc0tDp4ad/EyewESeXE/Iv67Aj8gKZ0',
crossorigin: 'anonymous',
},
],
}
数式をレンダリングする
クライアントサイドでレンダリングするには、ページがロードし終わったときに renderMathInElement
を呼び出す必要があります.
そのために、プラグインを作ります.ここでは ./plugins/docusaurus-plugin-katex-client
というプラグインを作ります(以降、katex-client
プラグイン).以下のようなフォルダ・ファイル構成にします.
└─ plugins
└─ docusaurus-plugins-katex-client
├─ index.js
└─ render.js
ここから、どのような仕組みになっているか説明します.
プラグイン
Docusaurusに機能を追加するにはさまざまな方法があります. プラグイン はその1つです.Docusaurusのプラグインは公式サイトによれば、次のように説明されています.
Docusaurus' implementation of the plugins system provides us with a convenient way to hook into the website's lifecycle to modify what goes on during development/build, which involves (but is not limited to) extending the webpack config, modifying the data loaded, and creating new components to be used in a page.
要するに、開発やビルドの中でフックして処理を入れることができるよ、という自分なりの解釈です.katex-client
プラグインでは、すべてのページ(グローバル)に対してフックし、特定のページだけ処理するといったようにします.
Client Modules
追加のJavascriptをすべてのページで処理するために Client Modules を使います. 具体的には renderMathInElement
を呼び出すJavascriptファイル(render.js
)をClient Moduleとして指定します.指定する場所はプラグインファイル(index.js
)です.
const path = require("path");
module.exports = function (context, options) {
return {
name: 'docusaurus-plugin-katex-client',
getClientModules() {
return [path.resolve(__dirname, "./render")];
},
};
};
ExecutionEnvironment
DocusaurusのSSGについてはこちらに説明があります.プラグインは開発やビルドにも影響があるため、ブラウザに表示されるときのみ処理するようにしたいです.そのために ExecutionEnvironment を使います.ExecutionEnvironment.canUseDOM
でブラウザに表示されるかどうかが判定できます.
import ExecutionEnvironment from "@docusaurus/ExecutionEnvironment";
export default (function () {
if (!ExecutionEnvironment.canUseDOM) {
return null;
}
// browser only
}