ウェブのYouTube動画埋め込みは遅延読み込みで

WordPressには、記事の作成エディタで1行の中にYoutubeの動画URLだけを書くと(ページ表示には)自動的にYoutube動画の再生画面にしてくれる便利な機能(oEmbed)がある。
コンテンツを作る側としてはメッチャ簡単なので嬉しいのだけど、これがページ表示の速さという面では非常によろしくない。ページ表示が遅いということは第一に閲覧者にとって良くない。そして、本来はオマケではあるが、Googleさんの評価が悪いのでそれはすなわちコンテンツを提供する側(記事を作る側)にも良くない。

WordPressの記事中にYoutubeの動画URLを書く。
https://www.youtube.com/watch?v=動画ID (同じ行に動画URL以外の文字を書くとおそらくNG)

これはページ表示時には以下のように展開され、Youtubeの動画プレーヤーが表示される。
<iframe title="動画タイトル" width="624" height="351" src="https://www.youtube.com/embed/動画ID?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

見れば判るがiframeの動画埋め込み形式になっている。これを普通に表示させようとするととても遅い。

Youtubeプレーヤー
こんなのが表示される。なお、上はただの画像なのでクリックしても何も起きない。

iframeタグのlazyload 1
このiframeのYouTube動画を埋め込んだページをGoogleのPageSpeed Insightsで採点してもらうと42点という驚きの低評価。「診断」の項目で「第三者コードの影響を抑えてください」という項目があるので展開すると、YouTubeのJavascriptがページ表示を邪魔していることが判る。YoutubeのCSSは、それ自体がページ表示の邪魔をしている時間はゼロということになっている。影響しているのは YouTubeの base.js と www-embed-player.js。

対策方法をググると、数行のJavascriptを書いてiframeタグのsrc="Youtubeの動画URL"をsrc=""に変更し、data-set="Youtubeの動画URL"を追加するという記事が多くヒットする。
でも、このやり方は他にLazy load系のスクリプトを使っているとコンフリクトする可能性があるし、何より2020年夏よりiframeの遅延読み込み(lazy-load)対応がウェブ標準になっている(Chromeなどの一部ブラウザでは2019年夏から)ので無駄な感じ。
シンプルにiframeタグ内に loading="lazy" を書くだけ。これで古いブラウザで表示する場合以外は問題無いしWordPress側を改造したりプラグインを加えて汚す必要もない、そして簡単。

ただし、WordPressでYoutube等の動画をURL1行記述にしていたらそれをiframe手書きに書き換えなきゃならないけど。

<iframe loading="lazy" width="854" height="480" src="https://www.youtube.com/embed/Q2zcPxCn3vg" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
黄色の文字列を追加するだけ。

それか、YouTubeの動画リンクの展開用のoEmbedの関数をオーバーライドするとか。 記事の最後に追記しました

iframeタグのlazyload 2
このページのYoutube動画の埋め込みは元から1つだけ。
そして、YouTubeの動画をURL1行書きからiframeタグのLazy Loadありに変えただけ。他は全く弄っていない。それだけで、42点から50点加点されて92点になる。というか、これまで無駄に50点減点されていた。いきなり点数が倍以上なのは笑う。
ちなみに、少し前までであればこれで100点になるのだが、最近は画像サイズと特にTTFBの判定が辛めになっているので100点にはならないことが多いかと。TTFBは、Googleさんは日本からの計測ではないようなのでCDNを利用していない日本だけにサーバがあるウェブサイトはちょっとキビシイ判定になる筈。この「がとらぼ」をKeycdnのPerformance Testで計測すると東京(Tokyo)での判定は120ms程度なのでサーバーが非力とはいえGoogleさんに指摘される程は悪くない筈なのよね。

この記事ではWordPressでYoutubeの動画URL1行記述を例に挙げたけど、YouTubeで表示される埋め込みコードを使う場合も同じこと。iframeタグにloading="lazy"を追加しましょう。
あと、YouTubeだけでなく、iframeは多くの場面で遅延読み込みで良いと思う。iframeがファーストビューの範囲にあると効かないと思うけど。

2021年3月10日追記: WordPress 5.7でiframeのLazyloadに対応したのでWordPress 5.7以降を利用の場合は以下を真似る必要はありません。

記事公開数時間後に追記

過去記事のYouTubeのURL1行記述と、手書きのiframeを探して loading="lazy" を追加しようとしたら、少ない筈と思っていたのが意外と多かった。そして「面倒だな」と思う気持ちが強くなってしまったのでYouTubeのURL1行記述の方はWordPressのfilterでオーバーライドする方が簡単そうに思った。

oEmbedについてはwp-includes/class-wp-oembed.phpを見た。
WordPressのoEmbedで対応する動画サイトやSNS等のURLもこのファイルに書かれてる。
m.youtube.com, www.youtube.com, youtu.be, *.vimeo.com, www.dailymotion.com, www.flicker.com, flic.kr, www.twitter.com, amazonいろいろなど、これはほんの一部で結構多く対応しているみたい。

で、oEmbedのタグにYouTubeのドメイン名(youtube.com, youtu.be)が含まれていたらiframeタグにloading="lazy"を追加するフィルタを作ってみた。

下のコードはWordPressで使用中のテーマのfunctions.phpの中に追加する。(wp-content/themes/使用中テーマ/functions.php)

1
2
3
4
5
6
7
function oEmbed_youtube_lazyload($tag){
  if(strpos($tag, 'youtube.com') !== false || strpos($tag, 'youtube.be') !== false){
    $tag = preg_replace('/iframe /', 'iframe loading="lazy" ', $tag);
  }
  return $tag;
}
add_filter('embed_oembed_html', 'oEmbed_youtube_lazyload');

もしくは、YouTubeだけでなく、とにかくoEmbedでiframeタグだったらloading="lazy"を追加するフィルタを作ってみた。YouTube以外でiframeが使われているのかを含めてこちらは動作未確認。そして、上のYoutube用フィルタとは同時に使わないでどちらか1つだけ。

1
2
3
4
5
6
7
function oEmbed_iframe_lazyload($tag){
  if(strpos($tag, 'iframe') !== false){
    $tag = preg_replace('/iframe /', 'iframe loading="lazy" ', $tag);
  }
  return $tag;
}
add_filter('embed_oembed_html', 'oEmbed_iframe_lazyload');