どうも、おひさです。
繁忙期過ぎても忙しくて、全然更新できなかった・・・。
というか、ドメイン死んでモチベーションが下がったw
さて、表記の件だが、
二回に分けて、
特に難しいかつ、重要視される、三つの課題をクリアできる記事にしようと思う。
今回は二つくらいクリアできるかな。
なんでこの書こうかと思ったかというのも、今年の10月あたりから、急にモバイルの基準が厳しくなったのはご存知だと思いますが、
当サイトも、それまで97点とかいってたのに、50点あたりまで下げられてしまい、なんとか、70点以上キープできるようになったのででした。
ほんとねー、余計なことすんなよ、Gよ・・・。
特に、WebPとか使えってったてさ、ほとんどのブラウザで表示できねーじゃねーかよ・・・。
と、愚痴はここまでにして、本題に入ろうか。
厳しくなる前でもあった項目もあるが、
特に難しい対策、敷設は、以下だろうと思う。
- ・レンダリングを妨げるリソースの除外
- ・次世代フォーマットでの画像の配信(効率的な画像フォーマットもほぼ併さる)
- ・オフスクリーン画像の遅延読み込み
今回は、上二つの対策方法をやっていこう。
■レンダリングを妨げるリソースの除外
これに関しては、実は悲しいことに、外部からCSS、JavaScriptを読み込んでいる限り、永遠に警告が消えない。
そんな言っても、インラインにしたら管理ができなくなるじゃん・・・。
ということで、サーバーサイドでインラインに出力しちゃおうというやつである。
実は、一回その記事書いたことあるんだよ。
今回は、それをちょっとだけ使いやすくしたものを公開しようかと。
今回はPHPだが、必要に応じて、PHP以外のサーバーサイド言語に書き換える必要があろう。
下記のPHPスクリプトをどこかに置き、
<?php /* ファイルを読み込み、インライン出力する */
define('SEARVER_SITE_ROOT', 'サーバーのルートパス書いとく');
// ↑は別に、下記で環境変数を使えば別に定義しなくてもいい
function cssOutput( $cssRoot = 'common/css/', $cssFileName = 'common' ) {
$cssFile = file_get_contents(SEARVER_SITE_ROOT . $cssRoot . $cssFileName . '.css');
if ($cssFile) {
$cssFileInner = str_replace("(../images", "(/" . $cssRoot . "images", $cssFile);
$cssLast = '';
$cssArray = explode("¥n", $cssFileInner); // とりあえず行に分割
$cssArray = array_map('trim', $cssArray); // 各行にtrim()をかける
$cssArray = array_filter($cssArray, 'strlen'); // 文字数が0の行を取り除く
$cssArray = array_values($cssArray); // これはキーを連番に振りなおしてるだけ
foreach ($cssArray as $key => $value) {
$cssLast .= $value;
}
// 複数行コメントアウトトル
$cssLast = preg_replace('/¥/¥*([^¥]|¥*[^¥/])*¥*¥//s', '', $cssLast);
return '<style type="text/css">' . $cssLast . '</style>';
}
}
function jsOutput( $filepath, $idText = null ) {
$js_str = file_get_contents( SEARVER_SITE_ROOT . $filepath );
if( $js_str === false ) {
return '';
} else {
return '<script' . ($idText ? ' id="' . $idText . '"' : '') . '>' . $js_str . '</script>';
}
}
んで、このPHPを読み込む。
<?php require_once( '/サーバーのルートパス/common/script/view_includ.php' ); ?>
実際に使うには、下記のようにする。
<?php // CSSを読み込む
// 第一引数には、cssファイル格納のディレクトリ、第二引数には、ファイル名を入れる
// 上記のようにするのは、画像の相対パスを解決するため
echo cssOutput('common/', 'common'); ?>
<?php // JavaScriptを読み込む
echo jsOutput('common/js/common.js'); ?>
これで、ファイル読み込み自体は、サーバーサイドで行われ、HTML上では、インライン出力となるため、
PageSpeed Insights(以下PSI)では文句を言われなくなる。
■次世代フォーマットでの画像の配信(効率的な画像フォーマットもほぼ併さる)
この課題をクリアするには、
大きく分けて二つの敷設を行う必要がある。
img要素に新フォーマットの画像を当て込むこと、
そして、CSSのbackground-imageに、新フォーマット画像を当て込むことだ。
img要素の置き換えはそんなに難しくない。
例えば、PNGだった画像にWebPを当て込むには下記のようにする。
<picture> <source srcset="hoge.webp" type="image/webp"> <img src="hoge.png"> </picture>
picture要素を使い、後方互換として、imgを入れ、従来の画像フォーマットを当て込めばいい。
こうしておけば、picture要素に対応しているブラウザはもちろん、
IEでも、pictureを無視し、imgを表示してくれるって寸法だ。
画像フォーマットには、WebPが一番適当だろう。
JPEG 2000、JPEG XRなどもあるが、
その中では普及率が高く、画質もそこまで変わらない。
(むしろ、JPEG 2000は若干重いような気がする)
だが、問題は、background-imageなどで指定する画像だ。
PSIのやつは、ここにまでチャチャをいれてくる。
JSで差し替えるのは意味がない。
Webページが読み込まれた時点で、WebPなりを使用していないと、警告がでるからだ。
そこで、先ほどのインライン出力スクリプトが役に立つ。
CSSファイル本体の方では、webpやjp2を使用したうえで、
先ほどのインライン出力スクリプトを下記のように書き換える
<?php /* ファイルを読み込み、インライン出力する */
define('SEARVER_SITE_ROOT', 'サーバーのルートパス書いとく');
define('INNER_UA', mb_strtolower($_SERVER['HTTP_USER_AGENT']));
define('IPHONE_FLG', (strpos(INNER_UA, 'iphone') !== false || strpos(INNER_UA, 'ipod') !== false));
define('ANDROID_FLG', (strpos(INNER_UA, 'android') !== false && strpos(INNER_UA, 'mobile') !== false));
define('WEBP_FLG', ( (strpos(INNER_UA, 'chrome') !== false && strpos(INNER_UA, 'edge') === false) || strpos(INNER_UA, 'opera') !== false ));
function cssOutput( $cssRoot = 'common/css/', $cssFileName = 'common' ) {
$cssFile = file_get_contents(SEARVER_SITE_ROOT . $cssRoot . $cssFileName . '.css');
if ($cssFile) {
// iPhoneの場合、いずれの場合もWebPは表示できないので差し替え
if (IPHONE_FLG) {
// 元がJPEGと示すため、URLパラメータを使用
$cssFile = str_replace(".webp?jpg", ".jpg", $cssFile);
$cssFile = str_replace(".webp", ".png", $cssFile);
}
// Androidは、jp2に対応していないので差し替え
if (ANDROID_FLG) {
$cssFile = str_replace(".jp2", ".jpg", $cssFile);
}
// PCでは、Google Chrome、Opera以外はWebPに対応してないため、差し替え
if (!WEBP_FLG && (!IPHONE_FLG && !ANDROID_FLG)) {
// 元がJPEGと示すため、URLパラメータを使用
$cssFile = str_replace(".webp?jpg", ".jpg", $cssFile);
$cssFile = str_replace(".webp", ".png", $cssFile);
}
$cssFileInner = str_replace("(../images", "(/" . $cssRoot . "images", $cssFile);
$cssLast = '';
$cssArray = explode("¥n", $cssFileInner); // とりあえず行に分割
$cssArray = array_map('trim', $cssArray); // 各行にtrim()をかける
$cssArray = array_filter($cssArray, 'strlen'); // 文字数が0の行を取り除く
$cssArray = array_values($cssArray); // これはキーを連番に振りなおしてるだけ
foreach ($cssArray as $key => $value) {
$cssLast .= $value;
}
// 複数行コメントアウトトル
$cssLast = preg_replace('/¥/¥*([^¥]|¥*[^¥/])*¥*¥//s', '', $cssLast);
return '<style type="text/css">' . $cssLast . '</style>';
}
}
// JavaScript出力メソッドは省略
CSSの出力をするスクリプトに、PHPでのブラウザ判定を行い、
それによって、WebPなどに対応していないブラウザでは、
拡張子を、従来の画像拡張子に差し替えているというわけだ。
これなら、PSIで点数を稼ぎつつ、全ブラウザで表示できるってわけ。
CSSと画像の運用も変えずに済む。
本当にね、今回のPSIのアップデートでイラっときたのは、
新しいフォーマット使えってことなんだよ。
そんなクッソ普及してない過疎フォーマット使えって、無理があるって。あほかって。
もっと、寛大な点数の付け方をしてもらいたいものだ・・・。
さて、次の記事では、これまた難しい、
オフスクリーン画像の遅延読み込みについてやっていく。
ではまた。

コメントする