Web

highlight.js のハイライト処理を Web Workers で実行する

投稿日:2021年3月15日 更新日:

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> で囲んで記述します(>&gt; と書きます)。

<pre><code class="js">window.addEventListener('DOMContentLoaded', (event) =&gt; {
  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ページが速く表示されるというのは、ユーザーの立場から見ても望ましいことです。

Web

シンタックス・ハイライト・ライブラリ「highlight.js」の使い方

2018.12.22
Web Vitals

highlight.js が引き起こすレイアウト・シフトを防止する

2021.02.01
Web Vitals

LCP を意識した Highlight.js の読み込み方

2021.02.04

📂-Web

執筆者:labo


comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

関連記事

Google

Googleマップで調べた経路をホーム画面に追加する (Android)

Android版の Googleマップで調べた経路は、ホーム画面にアイコンとして追加することができます。 手順は以下となります。 Google マップで調べた経路をホーム画面に追加する手順 (1) G …

Web

Mastodon(OStatus) を参考にして、理想の標準情報発信プラットフォームを考えてみました

話題の Mastodon を参考にして、私の理想とする情報発信プラットフォームについて考えてみました。 Mastodonとは? 見た目は、Twitterとほとんど同じサービスです。しかし、Twitte …

Google

【Google】アカウント無効化管理ツールの設定

Google の「アカウント無効化管理ツール」について説明します。

Web

Firefox で複数のプロファイルを使い分ける方法

目次1. Firefox のプロファイルについて2. プロファイルによって管理できるもの3. プロファイルの場所プロファイルの場所の確認方法4. プロファイルマネージャープロファイルマネージャーの起動 …

Web

URLリダイレクトの動作

URLリダイレクトの動きについて説明します。