highlight.jsがレンダリングブロックしたときの解決方法

highlight.jsがレンダリングブロックしたときの解決方法

ブログの記事内でソースコードをシンタックスハイライトしたくてhighlight.jsを使用しているのですがPageSpeed Insightsでサイト速度チェックしたらhighlight.jsがレンダリングブロックしてたのを最近になって気づきました。

highlight.jsでハイライトしたシンタックスはレンダリングブロックさえ解決してしまえば、イカしたナウいやつなのでレンダリングブロックの排除をして解決してみました。

 

highlight.jsでレンダリングブロックする原因

 

highlight.jsの公式からひっぱってきたCDNのライブラリを使うとレンダリングブロックしてました。

highlight.jsをCDNで使う場合は以下のライブラリです。

 

<link rel="stylesheet"href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.13.1/styles/monokai-sublime.min.css">

<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.13.1/highlight.min.js"></script>

<script>hljs.initHighlightingOnLoad();</script>

 

highlight.jsをCDNで読み込んで使うときにheadでスタイルシートとScriptを読み込んでbodyでScriptファイルを呼び出す感じですかね。

highlight.jsのライブラリがダメということでもなく使う方法も間違えてないのですが、レンダリングするときに同期的に読み込んでレンダリングされていることが原因になってレンダリングをブロックしてしまいます。

 

そもそもブラウザはページを表示するためにHTMLマークアップを解析してからDOMツリーを構築する必要があります。

 

解析の処理の途中でhighlight.jsのスクリプトが現れると、パーサーはHTMLマークアップの解析を停止してスクリプトを実行してから解析を続行します。

外部スクリプトの場合はリソースがダウンロードされるのを待つ必要があるのですが、highlight.jsで使うスクリプトのダウンロードによってネットワークラウンドトリップが発生し、ページが最初に表示されるまでの時間が長くなってしまい速度も落ちてしまう原因になってしまいます。

 

このへんのことを少し覚えておくとレンダリングブロックの解決が分かりやすくなってきます。

 

 

Advertisement

 

 

レンダリングを妨げるリソースの確認

 

PageSpeed Insightsで計測したレンダリングブロックの指摘はhighlight.jsのheadに置いたスタイルシートとScriptの2つが「レンダリングを妨げるリソースの除外」で指摘されていて改善案として教えてくれてるので解決のヒントに使えます。

 

 

サイズは1KBと19KB

短縮できる時間は230msと270ms(ミリ秒)

 

指摘されてるレンダリングを妨げるリソースの除外を解決すると

 

100ミリ秒が0.1秒なので0.5秒ほど表示速度の改善ができるということになります。

 

headで読み込んでるhighlight.jsのスクリプトがレンダリングのDOM構築を止めてしまってる感じですかね。

 

 

レンダリングをChromeデベロッパーツールで確認

 

 

 

Chromeデベロッパーツールでperformance結果やNetworkを確認すると、なんとなくレンダリングブロックの原因がわかったような気持ちになれます。

highlight.jsがレンダリングブロックしてるときを確認してみました。

 

 

 

デベロッパーツールのperformanceの見方はよく理解できてませんが、上の画像のレンダリングブロックしてるperformanceがレンダリングブロックを解決すると…

 

 

うっすい横線がhighlight.jsのスタイルシートとスクリプトのレンダリングがよーいドン!な感じなのでしょうか…

highlight,jsのスタイルシートは先読み込みされてスクリプトは他の処理を待たずに処理を始めてる感じです。

 

 

Advertisement

 

 

highlight.jsのライブラリは3つしかなく、少ないながらもイカしたナウいシンタックスハイライトをしてくれるので、どうせならライブラリすべてにテコ入れしておこうと思います。

 

レンダリングブロックを解決する読み込み方法

 

PageSpeed Insightsで計測したときの「レンダリングを妨げるリソースの除外」の改善項目を確認します。

ページの初回ペイントをリソースが阻害しています。クリティカルなjsやcssはインライン化し、それ以外のjsやスタイルは全て遅らせることをご検討ください。と改善案をおしえてくれています。

 

了解しました

 

勝手に了解したのでhighlight.js公式から連れてきたライブラリのJavaScriptは非同期にするスタイルシートは先読み込みをすることでレンダリングブロックを解決します。

 

スタイルシートにpreroadで先読み込み

 

link要素のrel属性が使われてるhighlight.jsのスタイルシートにpreroadを指定して読み込むようにします。

 

<link rel=”preload”>

 

preroadって先読みするという意味なので非同期なのかよくわかりませんけど、ファイルの読み込み完了を待たないでWebページのレンダリングは継続されます。

head内で読み込んでる重要ではないCSSファイルの読み込み待ちのでせいでページのファーストビュー描画が遅れることが解決できるので使い方としてはオッケーです。

 

 

<link rel="preload" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/styles/monokai-sublime.min.css" as="style" onload="this.rel='stylesheet'">

 

 

link要素に属性rel=”preload”を指定してから、そのファイルが読み込み終わった時点でonload属性値に記述したJavaScriptが実行されるので、そこでrel属性値がstylesheetに変わりcssとして読み込まれるようです。

 

Scriptにasyncをつける

 

インラインスクリプトは実行を遅らせる追加コードを記述しなければ必ずパーサーブロックになります。ということを以前にGoogle師匠のどこかで記事を読んだことがあるのでrel=”preload”にした方がいいのかもしれませんが、私にはよくわからなかったので以下を参考にしてみてください。

 

参考 MDN Web Docs スクリプトと先読み

 

今回のレンダリングブロックしてるhighlight.jsのスクリプトにはasyncをつけます。

 

 

<script async src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/highlight.min.js" ></script>

 

 

<script async src”…”>

 

asyncをつけたので非同期です!と宣言してるような感じですかね。

 

 

<script>window.addEventListener("load", function() { hljs.initHighlighting() });</script>

 

そしてもう一個には「addEventListener()」でinitHighlightingをサイトが読み込まれたときに実行できます。

 

それではhighlight.jsのレンダリングブロックを解決するコードをまとめた記述は以下です。

 

<link rel="preload" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/styles/monokai-sublime.min.css" as="style" onload="this.rel='stylesheet'">

<script async src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.15.6/highlight.min.js" ></script>

<script>window.addEventListener("load", function() { hljs.initHighlighting() });</script>

 

 

解決するhighlight.jsのコードはpreloadにしたスタイルシートとasyncにしたスクリプトを</head>直上に置いて、hljs.initHighlightingは</body>直上に置きます。

 

 

Advertisement

 

 

 

PageSpeed Insightsで計測するとhighlight.jsがレンダリングブロックしてた指摘と「レンダリングを妨げるリソースの除外」は解決できてます。

 

今後に活かすレンダリングブロックを解決する基本

 

最後に今後レンダリングブロックしたときの解決方法を考える基本にできると思い書いておきます。

 

ブラウザはスクリプトがページで実行する処理を知りません。そのため最悪のケースを想定してパーサーをブロックする必要があります。

ただしブラウザに対して「ドキュメント内で参照さている場所でスクリプトを実行する必要はない」と伝えれば、ブラウザでDOMを構築します。

ようはブラウザがレンダリングを開始してからHTMLの解析を始めます。そしてDOMツリーの構築をしてる途中でスクリプトに出会ってしまうと外部処理なスクリプトが、どう動くか見えないので結果がわかるまでブラウザはレンダリングの流れを待たされる。

 

関連 ブラウザレンダリングの仕組みを覚えておきたい

 

少しでもヒントになればいいなと思います。

 

Googleカテゴリの最新記事