Optimizing site performance by “lazy loading” images | Dries Buytaertで画像遅延読み込み(lazy loading)についての投稿があり、僕も過去に手間をかけずに Drupal で対応したことがあったので紹介します。
利用したライブラリ
Lozad.js:約 1kb の超軽量ライブラリ。Intersection Observer APIを利用しているので、動作も軽い。古いブラウザではpolyfillが必要。
サンプルコード
JS と CSS のコードは省きますが、テーマ(.theme)内に以下のように書きました。
/**
* Template_preprocess_image().
*/
function THEMENAME_preprocess_image(&$variables) {
if ($variables['style_name'] !== STYLE_NAME) {
$variables['attributes']['data-src'] = $variables['attributes']['src'];
$variables['attributes']['src'] = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
if (!isset($variables['attributes']['class'])) {
$variables['attributes']['class'] = [];
}
$variables['attributes']['class'] = array_merge($variables['attributes']['class'], ['lozad']);
}
}
画像 SEO 対策
if ($variables['style_name'] !== STYLE_NAME) {
ここで特定の画像スタイルを除外しています。全ての画像に適用したいなら不要。画像遅延読み込みは GoogleBot などが対応できなくて画像検索 SEO には不利との話もあるので、メイン画像だけ除外してます。
画像プレースホルダ
$variables['attributes']['data-src'] = $variables['attributes']['src'];
$variables['attributes']['src'] = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==';
出来るだけ軽量にしたかったのと手間を省きたかったので、プレースホルダは決め打ちにしました。https://dri.esでは Medium などと同様にそれぞれの画像ごとにプレースホルダを生成しています。
ライブラリ向けに Class の付与
$variables['attributes']['class'] = array_merge($variables['attributes']['class'], ['lozad']);
まとめ
僕の場合ファーストビューに必ず入ってくるメイン画像以外は遅延読み込みさせていますが、画面の表示エリアに入る前に読み込みが開始するように調整しているのでそもそも遅延読み込みしていることを閲覧者に気づかせないようにしています。また前述の通り SEO 的にもトレードオフがありますので、実装時はそのあたりの考慮も必要ですね。どちらの UX が良いかは考え方次第だと思います。
また、レイジーロードがブラウザネイティブでサポートされそうって話もあるのでそれはそれで興味あります。