レ点腫瘍学ノート

2020-07-22

WEBP画像のフォールバック

Top > pukiwikiカスタマイズ箇所 > 2020 > WEBP画像のフォールバック

JPGやPNGなどの画像をWEBP形式にすることによってファイル容量を減らすことができ、ひいては通信速度の向上によりPagespeed insightsのスコアの改善を期待することができます。しかしWEBP画像は現時点ではSafariに対応しておらず(近日中にMacとiOSのSafariはWEBP対応の予定)、IEでも開くことができません。このためWEBP画像を使用する場合は非対応ブラウザでは適切なfallbackを設定しておいて従来のJPGやPNGを表示できるようにしてあげなければなりません。

今回はrefプラグインで画像を保存しているフォルダに同名のWEBP画像があるかどうかを探してみて、もしWEBP画像あってかつ対応ブラウザであればWEBP画像を表示し、WEBP画像が存在しないか非対応ブラウザの場合にはもとどおりのJPG画像かPNG画像を表示するという改造を行いました。

WEBP画像のフォールバックとは

https://amp.dev/ja/documentation/guides-and-tutorials/develop/style_and_layout/placeholders/

高速化のためにWEBP画像を表示できるようにamp-imgを設定しつつ、もしWEBP画像が存在しなかったり非対応ブラウザの場合はJPGやPNGなどの互換性の高いファイル形式を表示できるようにしておくことです。amp-imgの場合は設定は簡単で、amp-imgタグの中にamp-imgタグを入れてfallbackと記載しておくだけです

<amp-img alt="Mountains"

width="550"

height="368"

layout="responsive"

src="/img/image.webp">

<amp-img alt="Mountains" fallback

width="550"

height="368"

layout="responsive"

src="/img/image.jpg"></amp-img>

</amp-img>

AMPページではなく通常のHTMLページでもAMPライブラリを読み込んでいればこの方法を使うことは可能といえば可能ですが、非AMPページではpictureタグを使うのが一般的かと思います。pictureタグはIEなどは非対応なので考慮する必要があります。

<picture>

<source srcset="image.webp" type="image/webp">

<source srcset="image.jpg" type="image/jpeg">

<img src="image.jpg">

</picture>

また、上記の真ん中の行は削除しても画像表示可能です。

<picture>

<source srcset="image.webp" type="image/webp">

<img src="image.jpg">

</picture>

リニューアルした日経電子版が高速すぎてヤバイ件 皆さんお読みになりましたか? 社内ではFastlyすごーい!!!って話が大きく感じましたが フロントに関係しそうな最後の方に出てくるWebPについてちょっとまとめてみました。 W...
https://qiita.com/mikimhk/items/abb525c304cf49f30350

具体的なref.inc.phpの改造内容

当サイトの環境

参考までに、当サイトでは基本的に画像を/img/フォルダに保存しています。また、AMP対応のためにもともとrefプラグインはAMP対応改造を実施していました。

WEBP画像は、画像が保存されている/img/フォルダとOGPプラグインのキャッシュが保存されている/cache/ogp/プラグインの中身をFTPでごっそり持ってきてWebPconvで一気に変換しました。WebPconvはほとんど初期設定のままですが圧縮のeffortだけ6に上げています(デフォルトは4)。Windows版しかありませんが多数のファイルを一気にWEBP変換するにはオススメです。 Photoshop CCを持っている場合はバッチ処理で変換してもいいかもしれません。

WebPconv | WebPconvはJPEG/PNG形式の画像をWebP形式に一括変換するアプリケーションです。WebP形式を様々な形式の画像ファイルに変換することも出来ます。
http://www.romeolight.com/ja/products/webpconv/

設定項目PLUGIN_REF_WEBP_FALLBACKの新設

まず「フォルダにWEBP画像を探してみてファイルがなければfallbackするか」を設定する項目を作っておきます。40〜41行目に下記の項目を新設しました。フォルダにWEBP画像を探してみるならTRUE、この改造を使用しないならFALSEです。

// フォルダにWEBP画像を探してみてファイルがなければfallbackするか

define('PLUGIN_REF_WEBP_FALLBACK', TRUE); // FALSE, TRUE

358-363行目

358行目付近の具体的な画像のHTMLタグ出力部を下記のように改造します。ちなみに、layoutはintrinsicでもresponsiveでも問題ないはずなのですが、なぜかintrinsicにしているとfallbackされた画像が表示されず真っ白になることがしばしばあり(リロードすると普通に読み込まれる)、responsiveのほうが安定しているような印象です。

AMP化改造を済ませた時点のrefプラグイン(改造途中)

PLUGIN_REF_URL_GET_IMAGE_SIZEをTRUEにしておく必要があります。

if ($is_image) { // 画像

$params['_body'] = "<amp-img src=\"$url\" layout=\"responsive\" alt=\"$title\" title=\"$title\" $info></amp-img>";

if (! $params['nolink'] && $url2)

$params['_body'] = "<a href=\"$url2\" title=\"$title\">{$params['_body']}</a>";

} else {

$icon = $params['noicon'] ? '' : FILE_ICON;

$params['_body'] = "<a href=\"$url\" title=\"$info\">$icon$title</a>";

}

FALLBACKの設定後のrefプラグイン(改造後)

if ($is_image) { // 画像

if ( PLUGIN_REF_WEBP_FALLBACK ) {

$urlwebp = pathinfo($url, PATHINFO_DIRNAME ) . '/' . pathinfo($url, PATHINFO_FILENAME ) . '.webp'; //同じディレクトリにwebp画像があるか探す

}

if ( PLUGIN_REF_WEBP_FALLBACK && file_get_contents($urlwebp)) {

$params['_body'] = "<amp-img src=\"$urlwebp\" layout=\"responsive\" alt=\"$title\" $info><amp-img fallback src=\"$url\" layout=\"responsive\" alt=\"$title\" $info></amp-img></amp-img>"; //webp画像fallback

} else {

$params['_body'] = "<amp-img src=\"$url\" layout=\"responsive\" alt=\"$title\" $info></amp-img>";

}

if (! $params['nolink'] && $url2)

$params['_body'] = "<a href=\"$url2\" title=\"$title\">{$params['_body']}</a>";

} else {

$icon = $params['noicon'] ? '' : FILE_ICON;

$params['_body'] = "<a href=\"$url\" title=\"$info\">$icon$title</a>";

}

AMP化していない場合のFALLBACKの設定後のrefプラグイン(改造後)

lazysizesスクリプトとpictureタグを使っています。pictureタグはAMPに非対応です。
またIEでpictureタグを正しく表記するためには、後述するjavascriptの読み込みが必要です。

if ($is_image) { // 画像

if ( PLUGIN_REF_WEBP_FALLBACK ) {

$urlwebp = pathinfo($url, PATHINFO_DIRNAME ) . '/' . pathinfo($url, PATHINFO_FILENAME ) . '.webp'; //同じディレクトリにwebp画像があるか探す

}

if ( PLUGIN_REF_WEBP_FALLBACK && file_get_contents($urlwebp)) {

$params['_body'] = "<picture><source type=\"image/webp\" data-srcset=\"$urlwebp\" alt=\"$title\" $info/><img class=\"lazyload\" src=\"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"$url\" alt=\"$title\" $info/></picture>"; //webp画像fallback

} else {

$params['_body'] = "<img class=\"lazyload\" src=\"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7\" data-src=\"$url\" alt=\"$title\" $info/>";

}

if (! $params['nolink'] && $url2) {

$params['_body'] = "<a href=\"$url2\" title=\"$title\">{$params['_body']}</a>";

}

} else {

$icon = $params['noicon'] ? '' : FILE_ICON;

$params['_body'] = "<a href=\"$url\" title=\"$info\">$icon$title</a>";

}

IEではpictureタグが正しく解釈できないという問題がありますが、picturefillというjavascriptを読み込ませることでIEなどでもpictureタグを解釈できるようになります。ChromeやFirefoxを含む最近のモダンブラウザはpictureタグの解釈はできますので、ブラウザを限定してjsファイルを読み込みます。なお、jsdelivrで見つかりにくいところにあるのですが下記のリンクは普通に機能しているようです(2020年7月現在)。これを<head>の下の方に配置しておきます。

<!--[if lt IE 11]>

<script src="https://cdn.jsdelivr.net/picturefill/2.3.1/picturefill.min.js"></script>

<![endif]-->

シェアしてね♪ Tweet 24時間注文・入稿受付OK。実績と信頼の「印刷の通販 グラフィック」 Tweet Picturefill.jsは、picture要素に対応していないブラウザでもpicture要素による画像の切?
https://techmemo.biz/javascript/picturefill-js/

なお、ほかに画像を出力するOGPプラグインなどもこの改造を実施しています。

Pukiwikiに様々なカスタマイズを加えてきたが、一般のブログサイトに似せたデザインにはできてもOGPの実装がなかなか難しいと感じていた。このPukiwikiのほかに「はてなブログ」を使っていたので、はてなブログの「ブログカード」は魅力的だと感じていた。また、このPukiwikiのURLをTwitterなどのSNSに貼ってもらった場…

追記:このフォールバックを設定してから、Googleのpagespeed insightsでFirst Contentful Paintが少し向上してページによってようやく1.0sを切ることができるようになり、また効率的な画像フォーマット次世代フォーマットでの画像の配信の判定が合格になりました。一方で最大コンテンツの描画の時間がごくわずかに(0.2sくらい?)遅くなってしまいました。これがフォールバックのせいなのかどうかは現在調査中です。

追記

2020.9.17未明にリリースされたiOS 14で、iPhone/iPadおよびMacのSafariもようやくwebpに対応しました。これでwebpはIE11を除くほとんどのブラウザに対応していることになり、JPEG 2000やJPEG XRを抜き去ってWebでの画像フォーマットの標準の地位を確固たるものにしました。

従来の画像ファイル形式より軽量かつ、可逆/非可逆圧縮・透過・アニメーションに対応したGoogle製の次世代画像フォーマット「WebP(ウェッピー)」についてのお話です。
https://dsinside.digitalstage.jp/entry/2020/08/19/100744