LoginSignup
6
2

More than 3 years have passed since last update.

wordpressでlazyload(Intersection Observer)

Last updated at Posted at 2019-04-25

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からのアクセスの時は何もしないというのがポイント。

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

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2