Wordpressのwebp、avif画像の読み込みを更に高速化する

## はじめに

https://qiita.com/nanakochi123456/items/adedfe54e50bbb3653d5

この記事を利用した、.htaccess によるリダイレクト型の
高圧縮画像表示には難点があり、
302リダイレクトが発生し、特に海外（米国）から計測すると
100バイト程度のリクエストとはいえ、
再度リクエストすることにより200ms～600msと大きな遅延を発生させてしまいます。

同じように国内においてもMVNO回線や電波の悪いモバイル回線でも同じようなことが発生しうると考えられます。


Wordpressとphpの知識を必要としますが、リダイレクトを発生をさせないよう、uaを検出して最適な画像を配信します。

### 必要なもの
・Wordpressのfunctions.phpの知識
・キャッシュ系プラグインのOFF、キャッシュ系のサーバー設定のOFF
・Wordpressで自動的にwebpに変換するプラグイン

今回はこれを使用、有料課金すればavifも使用できますが、webpだけの対応とします。

https://wordpress.org/plugins/webp-converter-for-media/

### functions.phpに記載するもの

```functions.php
/* 変換されたwebpを優先表示 */
function fastwebp($img) {
	// URLを変換すれば、相対URLにも近くなる
	$newimg=preg_replace('/https?:\/\/' . $_SERVER{'HTTP_HOST'} . '/i', '', $img);

	$newimgwebpc=preg_replace('/\/uploads/i', '/uploads-webpc/uploads', $newimg);

	if(filesize("." . $newimg . ".webp") > 4
	|| filesize("." . $newimgwebpc . ".webp") > 4) {
		if(canuse("webp") == 1) {
			$newimg=preg_replace(
				[
						'/\/uploads/i'
					,	'/\.png$/'
					,	'/\.PNG$/'
					,	'/\.jpg$/'
					,	'/\.JPG$/'
				],
				[
						'/uploads-webpc/uploads'
					,	'.png.webp'
					,	'.PNG.webp'
					,	'.jpg.webp'
					,	'.JPG.webp'
				], $newimg);

			return $newimg;
		}
	}
	return $img;
}

/* return 1=ok, 0=ng, -1=? */
/* リダイレクトも見た目にわからない時間がかかるのでブラウザ判別 */

function canuse($exec) {
	$useragent = browser_get_info();

	$platform=$useragent['platform'];
	$browser=$useragent['browser_name'];
	$majerver=$useragent['majorver'];
	$minorver=$useragent['minorver'];

	if($exec=="avif") {
		if($platform == "Android") {
			if($browser == "Chrome") {
				return $majerver>=100 ? 1 : 0;
			}
			if($browser == "Firefox") {
				return $majerver>=99 ? 1 : 0;
			}
		}
		if($platform == "Windows") {
			if($browser == "Chrome") {
				return $majerver>=85 ? 1 : 0;
			}
			if($browser == "Firefox") {
				return $majerver>=93 ? 1 : 0;
			}
		}
		return -1;
	}
	if($exec=="webp") {
		if($platform == "Android") {
			if($browser == "Chrome") {
				return $majerver>=100 ? 1 : 0;
			}
			if($browser == "Firefox") {
				return $majerver>=99 ? 1 : 0;
			}
		}
		if($platform == "iPhone" || $platform == "iPad" || $platform == "iPod") {
			if($browser == "Safari") {
				return $majerver>=99 ? 1 : 0;
			}
		}
		if($platform == "Windows") {
			if($browser == "Edge") {
				return $majerver>=18 ? 1 : 0;
			}
			if($browser == "Chrome") {
				return $majerver>=32 ? 1 : 0;
			}
			if($browser == "Firefox") {
				return $majerver>=32 ? 1 : 0;
			}
		}
		return -1;
	}
	return -1;
}

/* ブラウザーのバージョンを調べる */
/* get_browserでは処理が重すぎるのでこれを使用 */

function browser_get_info(){
	$ua = $_SERVER['HTTP_USER_AGENT'];
	$is_webkit = false;
    
	//Browser
	if(preg_match('/Edg/i', $ua)){
		$browser_name = 'Edge';
		if(preg_match('/Edge\/([0-9.]*)/', $ua, $match)){
			$browser_version = $match[1]; 
		}
		if(preg_match('/Edg\/([0-9.]*)/', $ua, $match)){
			$browser_version = $match[1]; 
		}
	}elseif(preg_match('/(MSIE|Trident)/i', $ua)){
		$browser_name = 'IE';
		if(preg_match('/MSIE\s([0-9.]*)/', $ua, $match)){
			$browser_version = $match[1];
		}elseif(preg_match('/Trident\/7/', $ua, $match)){
			$browser_version = 11;
		}
	}elseif(preg_match('/Presto|OPR|OPiOS/i', $ua)){
		$browser_name = 'Opera';
		if(preg_match('/(Opera|OPR|OPiOS)\/([0-9.]*)/', $ua, $match)) {
			$browser_version = $match[2];
		}
	}elseif(preg_match('/Firefox/i', $ua)){
		$browser_name = 'Firefox';
		if(preg_match('/Firefox\/([0-9.]*)/', $ua, $match)) {
			$browser_version = $match[1];
		}
	}elseif(preg_match('/Chrome|CriOS/i', $ua)){
		$browser_name = 'Chrome';
		if(preg_match('/(Chrome|CriOS)\/([0-9.]*)/', $ua, $match)) {
			$browser_version = $match[2];
		}
	}elseif(preg_match('/Safari/i', $ua)){
		$browser_name = 'Safari';
		if(preg_match('/Version\/([0-9.]*)/', $ua, $match)) {
			$browser_version = $match[1];
		}
	}
    
	//Webkit
	if(preg_match('/AppleWebkit/i', $ua)){
		$is_webkit = true;
		if(preg_match('/AppleWebKit\/([0-9.]*)/', $ua, $match)) {
			$webkit_version = $match[1];
		}
    }

	//Platform
	if(preg_match('/ipod/i', $ua)){
		$platform = 'iPod';
	}elseif(preg_match('/iphone/i', $ua)){
		$platform = 'iPhone';
	}elseif(preg_match('/ipad/i', $ua)){
		$platform = 'iPad';
	}elseif(preg_match('/android/i', $ua)){
		$platform = 'Android';
	}elseif(preg_match('/windows phone/i', $ua)){
		$platform = 'Windows Phone';
	}elseif(preg_match('/linux/i', $ua)){
		$platform = 'Linux';
	}elseif(preg_match('/macintosh|mac os/i', $ua)) {
		$platform = 'Mac';
	}elseif(preg_match('/windows/i', $ua)){
		$platform = 'Windows';
	}

	return array(
		'ua' => $ua,
		'browser_name' => $browser_name,
		'browser_version' => intval($browser_version),
		'majorver' => intval($browser_version),
		'minorver' => (explode('.',$browser_version))[1],
		'is_webkit' => $is_webkit,
		'webkit_version' => intval($webkit_version),
		'platform' => $platform
	);
}
```

### これは何をやってるの？

https://caniuse.com/

Can I use を元に調べた「メジャーな」ブラウザの対応をもとに、
HTTP_USER_AGENTを調べて

get-browser を使用してもいいのですが・・・・

https://www.php.net/manual/en/function.get-browser.php

browser.ini のサイズのあまりの巨大さで、処理が重くなりそうと感じ
軽量な手法で実装しました。

なお、派生ブラウザ、UA偽装したブラウザまでは対応していません。

また、上記のuaチェックで記載されていないものは
従来の形式で配信しようとし、302リダイレクトが発生する場合があります。