Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
2
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

wordpressでlazyload(Intersection Observer)

Google Developersに詳しく書かれているIntersection Observerを使った遅延読み込み手法。
イメージと動画の遅延読み込み| Web Fundamentals | Google Developers
ひと昔前はwindowのscrollイベントをhandleしてましたがこれがパフォーマンスが最悪という事で代わりに推進されています。polyfillする事で割と古いブラウザまで使えるのが良きかな。

wordpress内の画像に何も考えずに適用できんかなぁと思い、functions.phpに追記するのみで動くように書いてみました。
プラグインとか入れたくないし。

functions.php
// lazy load
function lazyload_attachment_image_attributes( $atts, $attachment ) {
  if(!empty($atts['class'])){
    if(strpos($atts['class'], 'lazyload') === false){
      $atts['data-src'] = $atts['src'];
      $atts['src'] = 'data:image/gif;base64,R0lGODlhAQABAGAAACH5BAEKAP8ALAAAAAABAAEAAAgEAP8FBAA7';
      $atts['data-srcset'] = $atts['srcset'];
      $atts['srcset'] = false;
      $atts['class'] .= ' lazyload';
    }
  }
  return $atts;
}
function lazyload_the_content( $content ) {
  $pattern ="/<img(.*?)class=\"(.*?)\"(.*?)>/i";
  $result = preg_match_all($pattern, $content, $matches);
  if($result > 0){
    $src_pattern = "/src=\"(.*?)\"/i";
    foreach ($matches[0] as $key => $match) {
      if(strpos($match, "lazyload") === false) {
        preg_match($src_pattern, $match, $src);
        $lazy_img = str_replace("src=", "data-src=", $match);
        $lazy_img = str_replace("srcset=", "data-srcset=", $lazy_img);
        $lazy_img = str_replace("sizes=", "data-sizes=", $lazy_img);
        $lazy_img = str_replace("/>", "src='data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==' />", $lazy_img);
        $lazy_img = str_replace('class="', 'class="lazyload ', $lazy_img);
        $content = str_replace($match, $lazy_img, $content);
      }
    }
  }
  return $content;
}
function loazyload_wp_head() {
  $script = <<<EOT
    <!-- lazyload -->
    <script src="https://polyfill.io/v2/polyfill.min.js?features=IntersectionObserver"></script><!-- polyfill -->
    <script>
      // lazy load
      document.addEventListener("DOMContentLoaded", function() {
        var lazyImages = [].slice.call(document.querySelectorAll("img.lazyload"));

        if ("IntersectionObserver" in window) {
          var lazyImageObserver = new IntersectionObserver(function(entries, observer) {
            entries.forEach(function(entry) {
              if (entry.isIntersecting) {
                var lazyImage = entry.target;
                lazyImage.src = lazyImage.dataset.src;
                lazyImage.onload = function(e) {
                  e.target.classList.remove("lazyload");
                };
                if (lazyImage.dataset.srcset !== undefined) {
                  lazyImage.srcset = lazyImage.dataset.srcset;
                }
                lazyImageObserver.unobserve(lazyImage);
              }
            });
          });

          lazyImages.forEach(function(lazyImage) {
            lazyImageObserver.observe(lazyImage);
          });
        } else {
          // Possibly fall back to a more compatible method here
        }
      });
    </script>
    <!-- /lazyload -->

EOT;
  echo $script;
}

function isClawler(){
  $ua = $_SERVER['HTTP_USER_AGENT'];
  $crawler_arr = array(
    "Googlebot"     // google
  ,"Baiduspider"        // Baidu
  ,"bingbot"        // Bing
  ,"Yeti"           // NHN
  ,"NaverBot"       // NaverBot
  ,"Yahoo"      // Yahoo
  ,"Tumblr"     // Tumblr
  ,"livedoor"       // livedoor
  );
  foreach ($crawler_arr as $value) {
    if (stripos($ua, $value) !== false) {
      return true;
    }
  }
  return false;
}
// bot以外の場合に遅延読み込みを設定する
if (!isClawler()) {
  add_filter('the_content','lazyload_the_content', 10, 2);
  add_filter('wp_get_attachment_image_attributes', 'lazyload_attachment_image_attributes', 10, 2 );
  add_filter('wp_head', 'loazyload_wp_head', 10, 2);
}

突貫ですが手元では問題なく動いていそうです。
画像検索にインデックスされるようにBotからのアクセスの時は何もしないというのがポイント。

実際動かしながら引き続きアップデートかけていきたいと思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
2
Help us understand the problem. What are the problem?