■【ファーストビュー関連】固定ページの最初の画像をpreloadで先読みする方法

コアウェブバイタルのLCP対策で、ブログ記事の最初の画像のみ、読み込み速度を上げるためpreloadで先読みさせ、ファーストビューの表示速度を上げる。

picture属性とsrcset&sizes属性の両方のパターンの記述メモ

■function.phpの記述(picture編)

<?php

//■固定ページの一番上の画像(data-がついていないpicture用の画像)をpreloadで先読み込み。
//※header.phpに呼び出し記述あり&ショートコードにも対応。

//preloadの読み込み形式に変換ここから
function catch_preload_image_page() {
global $post;
$image = '';

//正規表現で固定ページのファーストビューに設置してる画像を探す。
//※data-がついていないpicture要素の中のsource要素(複数)を探す。
$image_get = preg_match_all( '/(<source.*?media=["\'](.+?)["\'].*?\s(?!.*data-srcset)srcset=["\'](.+?)["\'].*>)/i', $post->post_content, $matches );

//探し出したsource要素を全部取得。
$all_source = $matches[1];

//テーマディレクトリのURLを取得。※ショートコード対策の一環
$uri = get_template_directory_uri();

//foreachで配列をすべて出力
foreach( (array)$all_source as $all_source_s ){
//取得したsource要素をすべて正規表現でpreload用タグに置換
//※この際、あらかじめ「media="(min-width:465px) and (max-width:880px)"」などとしっかりした範囲を固定ページ側で決めておくのがポイント。
//固定ページ中でショートコードを使ってテーマディレクトリを呼び出してるとショートコードのまま出力されるので、いったんsrcsetのテーマディレクトリのショートコードを抜いた$2を用意して、再度、テーマディレクトリのURLを入れる。※ショートコード対策
$image = preg_replace('/<source.*?media=["\'](.+?)["\'].*?srcset=["\'].+?(\/img.*?)["\'].*>/', '<link rel="preload" as="image" href="'.$uri.'$2" media="$1">', $all_source_s);

//置換した配列を出力して1行ごとに改行
echo $image."\n";
}

//$imageが空なら空のままにする
if( empty($image) ) {
$image = '';
}
return $image;
}

?>

上記の関数にてcatch_preload_image_page();呼び出されるのは下記の記述。

■関数にて呼び出されるpreloadの画像例

<link rel="preload" as="image" href="https://example.com/img/main-photo-01-2400-1200.jpg" media="(min-width:881px)">
<link rel="preload" as="image" href="https://example.com/img/main-photo-01-1760-990.jpg" media="(min-width:465px) and (max-width:880px)">
<link rel="preload" as="image" href="https://example.com/img/main-photo-01-928-928.jpg" media="(min-width:415px) and (max-width:464px)">
<link rel="preload" as="image" href="https://example.com/img/main-photo-01-750-750.jpg" media="(max-width:414px)">

■function.phpの記述(srcset&sizes編)

<?php

//■固定サブページの一番上の画像(data-がついていないsrcset sizes用の画像)をpreloadで先読み込み(※header.phpに呼び出し記述あり&ショートコードにも対応)
//preloadの読み込み形式に変換
function catch_preload_image_page1() {
global $post;
$image = '';

//正規表現で固定ページのファーストビューに設置してる画像を探す。※data-がついていないpicture要素の中のsource要素(複数)を探してる
$image_get = preg_match_all( '/<img.*?\s(?!.*data-srcset)srcset=["\'](.+?["\']).*?src=["\'].+?(\/img.*?)["\'].*?sizes=["\'](.+?)["\'].*>/i', $post->post_content, $matches );

//取得した一番上のsrcset要素を定義。※ショートコード対策
if ( isset($matches[1][0])) {
$srcset_first = $matches[1][0];
} else {
$srcset_first = '';
}

//テーマディレクトリのURLを取得。※ショートコード対策
$uri = get_template_directory_uri();

//固定ページ中でショートコードを使ってテーマディレクトリを呼び出してるとショートコードのまま出力されるので、いったんテーマディレクトリのショートコードを抜いて、再度、テーマディレクトリのURLを入れるために置換。※ショートコード対策
$pattern_img = array('/.*?(\/img.*?(,\s|"))/');
$replace_img = array($uri.'$1');//$1=テーマディレクトリのショートコードを抜いたsrcset要素。それにテーマディレクトリURLをつける。
$srcset_img = preg_replace($pattern_img, $replace_img, $srcset_first);

//探し出したsource要素の一番上の要素を取得してpreload形式にして書き出し。
if ( isset($matches[2][0]) || isset($matches[3][0]) ) {
$image1 = '<link rel="preload" as="image" href="'. $uri . $matches[2][0] . '" imagesrcset="'. $srcset_img . ' imagesizes="' . $matches[3][0] . '">';
} else {
$image1 = '';
}

//このままのpreload形式だとsizes属性がデバイスピクセル比3倍→2倍対策ができていないので下記の記述でsizes属性を変換。※必要ない時は記述ごと消して、上記のimage1をimageに変えてつなげる。
$pattern = array('/(.*?)(\(\s*(max|min)-width\s*:\s*\d+px\s*\))\s*(\d+px)\s*,\s*(.*?)/', '/(<img.*?)(calc\(\s*\d+px\s*\*\s*0.66\s*\)\s*,\s*)(\d+px)\s*[\"|\']/' );
$replace = array('$1$2 and (max-resolution:2dppx) $4, $2 and (min-resolution:3dppx) calc($4 * 0.66), $5', '$1$2(max-resolution:2dppx) $3, (min-resolution:3dppx) calc($3 * 0.66)"' );//置換
$image = preg_replace($pattern, $replace, $image1);

//置換した配列を出力
echo $image;

//$imageが空なら空のままにする
if( empty($image) ) {
$image = '';
}
return $image;
}

?>

上記の関数にてcatch_preload_image_page1();呼び出されるのは下記の記述。

■関数にて呼び出されるpreloadの画像例

<link rel="preload" as="image" href="https://example.com/img/img-1888-1062.jpg" imagesrcset="https://example.com/img/img-832-468.jpg 832w, https://example.com/img/img-928-522.jpg 928w, https://example.com/img/img-1888-1062.jpg 944w, https://example.com/img/img-1888-1062.jpg 1888w" imagesizes="(max-width:416px) and (max-resolution:2dppx) 416px, (max-width:416px) and (min-resolution:3dppx) calc(416px * 0.66), (max-width:464px) and (max-resolution:2dppx) 464px, (max-width:464px) and (min-resolution:3dppx) calc(464px * 0.66), 944px">

■header.phpの記述

<?php
//preload-page
if (is_page()){
$img_preload_page = catch_preload_image_page();
$img_preload_page1 = catch_preload_image_page1();
if (!empty($img_preload_page)){
$img_preload_page;
}else if( (empty($img_preload_page)) || (!empty($img_preload_page1)) ){
$img_preload_page1;
}else{
}};
?>

<head>内のスタイルシートより上に上記の記述を入れる。

上記はpicture属性とsrcset&sizes属性両方に対応した場合の記述。

Menu