PHPで別ファイルのHTML部品を読み込むinclude
を、できるだけ簡単にJavaScriptによる非同期読み込みに変えちゃおうという試みです。名付けてLazy Include
。
php-lazy-include
https://github.com/miyanaga/php-lazy-include
画像の遅延読み込みLazy Load
もちょっとしたHTMLとJavaScriptのトリックですが、それをHTMLの断片にまで拡張したものです。
※ 上記のソースコードは実用的なライブラリではなく、コンセプトの実装例です。ぜひ改良してみてください!
コンセプト
ソースコードはよく見るPHPのinclude
です。
<div>Main File</div>
<?php include('includee.php') ?>
include
される側のファイルも通常通りHTML断片を出力するPHPですが、先頭と末尾に1行ずつ決まったおまじないが記述されています。
<?php if(include('lazyInclude.php')) return ?>
<div>Sub File</div>
<?php endLazyInclude() ?>
結果
上記のソースが実行されると、次のようなHTMLとJavaScriptに展開されます。
include
を行った場所にひとまず目印となるdiv
要素を置いておき、DOMContentLoaded
イベントでそこに元々include
されるはずだった内容を展開するという流れです。
<div>Main File</div>
<!-- 非同期にincludee.phpの内容を展開する目印 #the-lazy-include -->
<div class="lazy-include" id="the-lazy-include"></div>
<script>
/* <script src="/includee.php?id=the-lazy-include"> をbody末尾に追加 */
window.addEventListener('DOMContentLoaded', function once() {
window.removeEventListener('DOMContentLoaded', once);
var script = document.createElement('script');
script.setAttribute('src', "\/includee.php?id=the-lazy-include");
document.body.appendChild(script);
});
</script>
body
に追加されたscript
要素は次のJavaScriptを読み込んで実行します。
/* 目印 #the-lazy-include にincludee.phpの本来の内容を展開 */
document.getElementById("abc").innerHTML = "<div>Sub File<\/div>\n";
2行のおまじないを追加すると、JavaScriptによる非同期include
になり、そのおまじないを除去するとPHPによる普通の同期include
に戻るというものです。
何が嬉しいの?
ページの読み込み直後のレンダリングから、Lazy Include
したDOMを除外することで表示の高速化を図っています。
「PageSpeed Insightsの点数はどのように計算されているか。100点をとるための条件」という記事で、PageSpeed Insightsの点数においてはファーストビューの描画時間が重要であると書きました。
このHTMLデータ自体の軽量化もさることながら、初期のDOMのオブジェクト数を減らすことはPageSpeed Insightsの点数アップにもよい影響が期待できます。
そのような非同期処理が、JavaScriptの記述不要で簡単に実現できます。
ユースケース - ボリューム感のあるフッター
フッターにサイトマップをまるごと掲載するサイトが増えています。サイトによってはクローラー向けの内部リンク目的だったり、デザイン上どっしりボリューム感を出す目的かもしれませんが、ユーザーにとっては無駄の多いコンテンツ
です。
- たまに役立つかもしれないがそこまで滅多にスクロールしない。
- 大規模サイトだとけっこうなHTMLの量とDOMオブジェクトの数がある。
- ほとんど変更されないのに毎回毎回、HTMLに含まれて送信される。
もしSEO上の意図がないのであれば、Lazy Includeによって少し後でレンダリングすることで次の効果が期待できます。
- 読み込みとファーストビューの描画が速くなる。
- JavaScriptのキャッシュでブラウザにキャッシュを持たせることもできる(上記コードでは
Expires
ヘッダは未実装)