Prism.jsによるSSRを試す
はじめに
先日はMathJaxとKaTeXによるSSRを試してみたが、今回はPrism.jsのSSRを試してみる(最近はSSRに興味が出てきたので勉強中である)。普段、Prism.jsを利用するときは雑にPrism.highlightAllUnder(document, false)
で済ませてきたが、もう少し一般的な利用方法も示していきたいところである。
以下のドキュメントによれば、Prism v2を現在開発中とあるが、動いているのか不明である。現在のバージョンのPrism.jsが保守されなくなるのではという懸念点があるが、他のシンタックスハイライターに乗り換えるコストはあまり高くはないだろうし、乗り換えが必要になるような事件もそうそう起きないだろうから、利用を継続する(乗り換えは必要になってからで十分)。
Prism.jsを利用する際は以下を実行して導入をする。
今回利用したパッケージのバージョンは以下のとおりである。
単純なソースコードのハイライト
特に何も考えずにレンダリングをしたい場合、以下のように出力することができる。ほぼサンプルからの流用である。スタイルが絡む分、単純というよりは低レイヤといった方が正しいかもしれない。
ただ、現実的にCSSを自前で用意するのは面倒なため、用意されたテーマを利用するのが普通である。CSSはテーマやプラグインごとに存在しており、これらをすべてリンクして利用するのは酷なため、webpackおよびCSSのバンドルのためのプラグインを利用する。
今回利用したパッケージのバージョンは以下のとおりである。
webpack.config.js
の設定については以下を参考にしてのように行った。
あとは、メインとなるJavaScriptのスクリプト中で依存関係にあるCSSをインポートすれば、style.css
がカレントに生成されるようになる。ただ、JavaScriptのバンドルについては、Prism.jsはその仕組み上、言語に関するモジュールが動的に相互依存しているという面倒な仕組みをしているため、以下のように手動でインポートをする。
これらの言語モジュールの依存関係についてはnode_modules/prismjs/components.js
やnode_modules/prismjs/components.json
に記述されている。例えば、C++モジュールの場合であれば以下のような記述があるため、C言語のモジュールに依存していることがわかる。
しかしながら、これは非常に面倒なため、JavaScriptをバンドルしないようにする(ハイライトはサーバで完結させる)、セルフホストする、以下からダウンロードしたものをバンドルするとした方がはるかに簡単だろう。そもそも本記事はSSRを行うことが目的なので、そんなことは気にする必要はないが。
実際に生成したHTMLは以下のコードのコメント部に挿入することにより、いい感じにハイライトされた表示を確かめることができる。
ちなみに、全ての言語をバンドルするためのJavaScriptファイルをインポートをするスクリプトは以下のように簡単に実装をすることができる。
プラグインの利用
Prism.jsにおけるプラグイン、例えばnode_modules/prismjs/plugins/line-numbers
にあるものは行番号を付与するものであるが、明らかにdocument
に依存しているためそのままではSSRを行うことができない。というわけで、JSDOMを利用してそれを回避する。
今回利用したパッケージのバージョンは以下のとおりである。
また、Prism.jsのプラグインは基本的にDOMの構造に依存して利用されるものであり、Prism.highlight
では機能しない。そのため、HTMLファイルを用意しておく。ハイライトを行うコードはC++による「Hello, Wirld.」である。
具体的なdocument
などの参照を回避するコードは以下である。global
に色々オブジェクトを設置した作為のあるコードである(特にgetComputedStyle
あたり)。ファイルへの出力については一通りのイベントの発火後ということで、マイクロタスクにファイルの出力のコードを積んでいる(多分必要はない)。
おわりに
MathJaxやKaTeXでのSSRの時も思ったが、全然素直に動いてくれなくて辛いものを感じる。それは多分私がフロントエンド素人であることが原因の1つだろう。ブログ運営のためにJavaScriptは勉強しているが、それ以外の場面で使ったことはないので、ノウハウはない。
とりあえず、MathJaxとKaTeX、Prism.jsのSSRは調べたから、次はmermaid.jsのSSRを調べると思う。ただ、今はGWなので明けてから考えることにする(ブログのシステム部分で利用したいとは思っているが、利用は未定である)。