1. highlight.js の利用方法
Webページ上でシンタックスハイライトを行う JavaScript ライブラリ「highlight.js」ですが、普通に読み込んで使うとページの読み込みや表示に時間が掛かってしまいます。Web Vitals の指標でいうと Largest Contentful Paint (LCP) の評価が低下するということです。
しかし「Web Workers を使って highlight.js を利用する方法」であれば、ページの読み込みに時間が掛かる問題をかなりのところまで低減できますので、その方法を紹介します。
2. highlight.js を使う一般的な方法
念の為、highlight.js を利用する一般的な方法もここに書いておきます。
※ この内容は、How to use highlight.js に書いてあります。
例えば、Webページに JavaScript コードを載せる場合であれば、まずそのコードを <pre><code class="js">
と </code></pre>
で囲んで記述します(>
は >
と書きます)。
<pre><code class="js">window.addEventListener('DOMContentLoaded', (event) => {
console.log('DOM fully loaded and parsed');
});
</code></pre>
あとは、highlight.js の CSS ファイル・JavaScript ファイルを読み込み、hljs.highlightAll();
という JavaScript コードを実行するように記述します。
<link rel="stylesheet" href="/path/to/styles/default.css">
<script src="/path/to/highlight.min.js"></script>
<script>hljs.highlightAll();</script>
以上により、JavaScript コードがハイライト表示されます。
この方法は簡単でよいのですが、先程書いたように「ページの読み込み」や「ページを表示する処理」に時間が掛かります。
3. Web Workers を使った highlight.js の利用方法
次に Web Workers を使った方法です。
こちらも How to use highlight.js で説明されているのですが、最低限の説明しかありません。ここではもう少し実用的なところまで付け加えて説明します。
先程と同様に、Webページに JavaScript コードを載せる場合であれば、まずそのコードを <pre><code class="js">
と </code></pre>
で囲んで記述します。ここはもちろん同じです。
次に以下の内容を記述した JavaScript ファイルを作成してWebサーバー上に配置し、クライアントからアクセスできるようにしておきます。ここでは、このファイルの名前を hljs-worker.js
とします。
onmessage = function(event) {
importScripts('/path/to/highlight.min.js');
const result = self.hljs.highlightAuto(event.data);
postMessage(result.value);
}
そして HTML 側には、以下の JavaScript コードを記述します。
<script>
addEventListener('load', function() {
//--------------------------------------
// Apply highlight.js using Web Workers
//--------------------------------------
(() => {
// 処理を軽くするため、なるべく対象を絞ったセレクタを指定する
const codes = document.querySelectorAll('pre > code');
// <pre><code> がなければ、ここで処理を終了させる
if (codes.length == 0) return;
// Add stylesheet link
const link = document.createElement('link');
link.rel = 'preload';
link.href = '/path/to/styles/default.css';
link.media = 'all';
link.as = 'style';
link.onload = function() { this.rel = 'stylesheet' };
document.querySelector('head').appendChild(link); // CSSファイルが読み込まれる
// <pre><code> 毎に highlight.js でハイライトする
codes.forEach(code => {
// nohighlight クラスが指定されていれば何もしない
if (code.classList.contains('nohighlight')) return;
code.classList.add('hljs');
// code 毎に専用の onmessage をセットするので、それぞれに専用の Workerインスタンスが必要
const worker = new Worker('/path/to/hljs-worker.js');
worker.onmessage = event => code.innerHTML = event.data;
worker.postMessage(code.textContent);
});
})();
})
</script>
処理の内容については、コメントに書いておきました。
ポイントは以下です。
- ページ上に
<pre><code>
がなければ、highlight.js の CSS ファイル・JavaScript ファイルが読み込まれることはありません。 - ハイライトするページでも、メインスレッドとは別のスレッドでハイライト処理が実行されるので、Core Web Vitals の指標への影響はかなり小さいです。
<pre><code>
毎に Worker インスタンスを生成しており、hljs-worker.js
ファイル内のimportScripts()
がその回数だけ実行されますが、highlight.min.js
ファイルはブラウザで最初の1回でキャッシュされたものがそれ以降利用されます(Webサーバーとブラウザの設定にも依りますが)。
4. まとめ
highlight.js の一般的な利用方法と比べると、Webページの表示がかなり速くなります。最近重要になってきた Core Web Vitals という指標を重視するのであれば、Web Workers を使った方法しかありえないという判断になるはずです。手順は少し面倒ですが、Webページが速く表示されるというのは、ユーザーの立場から見ても望ましいことです。