blog_intersection_observer00

ブログのトラブル復旧ついでに、Intersection Observer でブログの高速化に挑戦

記事公開日:2019年2月28日

こんばんは。
久々の投稿です。

今回は、私のブログのトラブルから復旧させるついでに、Google PageSpeed Insights の改善案をもとに、思い切って、Intersection Observer 等を使ったブログの高速化に挑戦した、というご報告です。

先月中旬頃、ブログのメンテナンスで、外部画像サービス Flickr から自サーバーへ全面移行する作業中に、誤って特殊文字や空行を消してしまい、その修復作業に追われていました。
その間、ブログをご覧になった方々やお問い合わせやコメント投稿して下さった方々、大変ご迷惑をおかけしました。
m(_ _)m
現在、全面復旧しましたので、ソースコードで不具合が出た方は改めて再確認をよろしくお願いいたします。

スポンサーリンク

さて、ブログを運営されている方々、最近の PageSpeed Insights の評価があまりにも厳し過ぎませんか?

私は、PageSpeed Insights対策方法が難し過ぎると感じたので、今まで敬遠していました。
ですが、実際、踏み込んで取り組んでみると、かなり効果があることが分かりました。
特に、画像や Youtube 動画の埋め込み対策は劇的に効果がありました。

それに合わせて、Amazon リンク画像も遅延読み込みさせたら、かなりアクセス速度があがりました。
(今回は Amazon リンク対策は紹介していません)

その他、画像やCSS最適化もすることによって、パソコン用に限って言えば、PageSpeed Insights の評価をかなり上げることができ、ブログのアクセスも体感的にスピードアップできたと思います。
モバイル用は残念ながらまだまだ対策が必要ですが、私の今の実力ではここまでが限界のように思います。

ということで、今回はその対策の一部、Intersection Observer を紹介してみようと思います。

因みに、私は Web 関連プログラミングは素人です。
誤りや勘違いがあるかもしれません。
もしお気づきの点がありましたら、コメント投稿等でご連絡いただけると助かります。

    【目次】

  1. ブログのトラブル経緯と高速化対策を決意した切っ掛け
  2. Intersection Observer でオフスクリーン画像の遅延読み込み
  3. Youtube 埋め込み動画のオフスクリーン遅延読み込み
  4. その他の対策
  5. まとめ

ブログのトラブル経緯と高速化対策を決意した切っ掛け

Flickr の画像を自サーバーへ移行するはめに・・・

先月中旬まで、このブログの画像は、外部サービス Flickr の無料枠を使っていました。

WordPress との相性が良く、画像がサクサクアップできて、サクサク記事に反映できて、とっても重宝していました。
1TB まで無料でアップロードできるということで、気兼ねなくガンガンとアップしていました。

しかし、先月中旬頃、ふと気付きました。
なんと、2019/02/08から Flickr の無料枠が写真1000枚に制限されるというのです。

有料アカウントに切り替えるという手もありましたが、お金も無かったし、外部サービスに左右されるのはウンザリだったので、思い切って全画像を自サーバーに移行することにしました。

さぁ、それからが大変なことに・・・。

WordPress Search Regex の使い方を誤り、全記事の文字消えトラブル

Flickr の HTML タグは、Wordpress のテキスト置換プラグイン、Search Regex を使えば、意外と楽にいけるかなぁと思っていましたが、これが大間違いでした!!!
Flickr の HTML タグが思いの外、多種多様で困り果てました。

そこで、大の苦手だった正規表現を覚えなければいけない事態になりました。
この正規表現って、実際にちゃんと覚えて使ってみると、スゲーと思いました。

正規表現、便利過ぎます!!!

ただ、これを誤って使ってしまい、ブログに掲載しているソースコードの”¥”マークや、空白行を消してしまったようなのです。
本文の文章の空行も消えていました。

もしかしたら、Wordpress のバージョンが 5.0 に上がった時、ブロックエディターなるものが登場して、これが原因かと疑いました。
しかし、どうやら、私自身の Search Regex の使い方を誤ったことが原因だったようです。

それも、気付いたのが2月に入ってからなので、その間に一つ記事をアップしていました。

「ヤベェ~・・・!!!」

その間、コメント欄で、ソースコードがちゃんと動かないという質問を数人から頂きました。
それも恐らくこれが原因だったのです。

復旧させるためには、全記事をバックアップファイルから全復旧させねばなりませんでした。

WordPress 記事全面復旧のやり方が分からず、悪戦苦闘

こういう時に備えて、バックアップは頻繁に取っていたのですが、Wordpress で全復旧というのは今まで一度もやったことありません。
さぁ、困った・・・。

私はレンタルサーバーの Xserver を使っていますが、自動バックアップサービスは使っていませんでした。
手動でバックアップしていました。

一度、手軽なXML ファイルから復旧させてみましたが、どうもうまくいきません。

ならば、ローカル環境でテストしなければならないと思ったので、XAMPP でローカルのサーバー環境を構築して、試験してみることにしました。

しかし、どうもうまくいきません。

ならば、レンタルサーバーと同じ環境にすべく、PHP 5 を PHP 7 にアップデートしてみました。
これが、とっても難解な作業ばかりで、心が折れそうでした。
phpMyAdmin がとってもややこしいんですよね・・・。
でも、そんなこんなで、何とか PHP 7 にアップデートを終えました。

XML の復旧がうまくいかなかったので、仕方なく、超難解な MySQL というデータベースで復旧を試みました。
ただ、ローカル環境で MySQL を動かすこと自体、とっても大変!!!

ですが、いろいろ悪戦苦闘した結果、MySQL を使った復旧ができました。
そうしたら、素晴らしく完璧な復旧ぶりだったのです。

MySQL すばらしい!!!

なるほど、MySQL を使う理由がよ~くわかりました!!!

そんなこんなで、ローカル環境で何度もテストできたおかげで、レンタルサーバーで本復旧も実践してみて、無事、復旧できました。
XAMPP などでローカルサーバー環境を整えることが、こんなにも重要な事だったとは、改めて思い知らされました。

そして、最新記事や、コメント投稿も復旧させることができました。

外部の画像サービスは使わないと決心。でも、無料サービスに感謝しよう!

復旧が上手くいっても、1月中旬の記事に戻っただけなので、Flickr の HTML タグも元に戻ってしまいました。
よって、また1から Flickr タグの移行作業という地獄・・・。

もう、気が遠くなりました・・・。

それでも、コツコツと何とか全て移行完了しました。
再び1週間くらい、全ての空いた時間がこれに費やされ、気が狂いそうでした。

「この時間を返してくれ~い!!!」

この時ほど、
「無料ほど高い物は無い!!!」
と実感したことはありません。

もう2度と画像の外部サービスは使うまいと決心しました。

まぁ、それでも、今まで数年間、無料サービスの便利さを味わっていたので、感謝しなければならないとも思いました。
無料で使えるものを開発している人たちは、かなりの技術と労力を払ってシステムを作り上げてきたので、それを使わせてもらっただけでも感謝せねばなりません。
やっぱり、開発者にもちゃんと対価を払わねば生きていけませんから、有料化するのも納得です。

Flickr さん、今までありがとう!!!
m(_ _)m

Google PageSpeed Insights の評価があまりにも低すぎて困った

なんだかんだ、何とか復旧したら、今度はブログのメンテで使っている Google Search Console から、Google bot によるクロールエラー通知が届くようになりました。

そのエラーを修正しているうちに、私のブログのアクセスがやたらと遅く、ブラウザ Google Chrome のデベロッパーツールでタイムアウト警告がやたらと出現することに気付きました。

Google Chrome デベロッパーツールの警告は、拡張機能のセキュリティ関連プラグインや、Google Analytics オプトアウト、Google Publisher Toolbar を使っていると、それによる警告がでることは分かっていたので、これを全部解除してみたり、シークレットモードで起動してみたりしました。
それでも、消えない警告がありました。

Google PageSpeed Insights の評価も5という超低評価。

数か月前から、何か遅いなぁとは思っていましたが、気になったのでいろいろと調べていると、実は、Amazon 広告リンクが原因だったのです。

Amazon 広告リンクのタイムアウトによる原因

私の場合、Amazon 広告リンクは WordPress プラグイン
Amazon Associates Link Builder
を使っていました。

私の場合、記事の最初のページに Amazon 販売商品を多数紹介して掲載していたので、ブラウザが Amazon からの商品画像を一気に取得して記事を表示していました。

これが、画像を取得後、なぜかいつまで経ってもアクセスが続いたままで、20~30秒後にタイムアウトしていたのです。

プラグインが悪いのかと思い、試しに Amazon アソシエイトページのHTMLタグを直貼りしてみました。
でも、それでもタイムアウトしました。

Amazon ヘルプセンターに問い合わせたり、いろいろと調査したりしていると、プラグインの最新版がリリースされたので、早速最新版に更新しました。
これは2/9頃のことでした。

そうしたら、やっとタイムアウト問題解消!!!

Firefox ブラウザの良さが分かった

私は今まで Google Chrome 信者だったのですが、Amazon ヘルプセンターに問い合わせた時に、Firefox ブラウザでもぜひ確認してみて欲しいと助言を頂きました。

そんなに Firefox って信頼あるのかな? と思いました。

試しに、私のパソコンにインストールしてみて、開発者ツールを開いてみると、これが何とも Google Chrome よりも格段に見やすいのです。
そして、とっても使いやすい。

Google Chrome は英語ばかりで、謎のメッセージが多かったのですが、Firefox は日本語メッセージが多くて、超使いやすいです。
多くのプログラマーが勧める理由が、今回よーくわかりました!!!

とりあえず、Webで公開するにあたっては、いろいろなブラウザで検証してみることが大事だなということが改めて実感した次第です。
この日を境に、Windows Edge、Internet Explorer も数年ぶりに使って検証するようになりました。

ブログのレンダリングを妨げていたものをあぶり出して、ブログの高速化を挑戦することに・・・

ようやく正常に戻ったのが 2/10 頃。

でも、Google PageSpeed Insights が未だに低すぎる。
アクセス速度も改善されたものの、やっぱり重い。

モバイル環境では10~20という低評価。

改善できる項目の
「レンダリングを妨げるソースの除外」
「オフスクリーン画像の遅延読み込み」
というところで、特にひどかったのが、初回アクセス時にそのページの画像を全て一気に取得してしまうことだったのです。
それには、先ほども述べたように、Amazon の画像も含まれています。

私の場合、最初に「準備するもの」や「使ったもの」と題して、使った商品を画像付きで紹介したり、Amazon 広告リンクを載せたりしています。
それが最初の記事ページに多量にあると、アクセスが重くなってしまうのです。

そんなわけで、これを解消するために、
「オフスクリーン画像の遅延読み込み」
つまり、画面に出ていない画像は読み込まず、スクロールして画面に出る直前に画像を読み込むという対策をする必要に迫られました。

この有効な対策が JavaScript と HTML で構築する、Intersection Observer というものです。

これは、最初は難解なように見えましたが、実際にやってみると、それほど難しくなく、意外と簡単でした。

ということで、私のやった対策を簡単に紹介します。

Intersection Observer でオフスクリーン画像の遅延読み込み

画面に映っていない画像は読み込まずに、ユーザーがスクロールさせて画像が現れる直前に読み込ませるためには、Intersection Observer が有効だそうです。
これは、ググればいろいろな方々が実現されていて、とっても詳しい解説をされている方々が沢山いらっしゃいますので、私は簡単にザッと説明します。
最近は多くのウェブサイトで取り入れているみたいで、もはや装備しているのが当たり前だったみたいですね。

以前、調べたことがあったのですが、ちょっと難しかったので敬遠していました。
でも、先に述べたように、今回は避けて通れなくなったので、思い切って私のブログに実装してみました。

因みに、対応ブラウザは以下のページで確認できます。

https://caniuse.com/#search=intersection

Internet Explorer 以外、最新のメジャーブラウザならば、多くが対応していますね。
ですが、ブログで公開するには、ある程度未対応ブラウザにも対応しなければいけませんね。
Google PageSpeed Insights からたどれば、解決方法を紹介してくれているページが見られます。

https://developers.google.com/web/fundamentals/performance/lazy-loading-guidance/images-and-video/?hl=ja

私の場合は、そのコードをほんのちょっと改変し、以下のスクリプトコードをfooterの直前、または</body>タグの直前に置きました。

<script src="https://polyfill.io/v2/polyfill.min.js?features=IntersectionObserver"></script>
<script>
  document.addEventListener("DOMContentLoaded", function() {
    var lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));

    if ("IntersectionObserver" in window) {
      let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
        entries.forEach(function(entry) {
          if( entry.intersectionRatio > 0 ) {
            let lazyImage = entry.target;
            lazyImage.src = lazyImage.dataset.src;
            lazyImage.classList.remove("lazy");
            lazyImageObserver.unobserve(lazyImage);
          }
        },{ root: null, rootMargin: "0px 0px", threshold: [0.0] });
      });

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

このコードの rootMargin や threshold を変更すれば、スクロール位置による画像読み込みを変えることができます。

実際にブログに埋め込む際には、スクリプトの空白行とか改行およびコメント行を削除して少量化(minify化)させて貼り付けています。

また、最初の行にある、https://polyfill~というスクリプトリンクは、Intersection Observer が対応していないブラウザ用のスクリプトです。
非対応ブラウザ用のライブラリは Polyfill っていうみたいですね。
この名前は今回初めて知りました。
Webの世界は専門用語が多くて、難解です・・・。
これがあれば、非対応の Internet Explorer でも画像の遅延読み込みが可能です。

そして、実際に画像を埋め込む HTML タグは以下です。

<img src="" data-src="https:/xxxx/imagefile.jpg" alt="img1" class="lazy" width="600"/>

srcに画像ファイルが指定されておらず、空というところがポイントです。
代わりに、data-src に画像ファイルを指定しています。
これが不思議なところです。

srcに画像ファイルを指定してしまうと、最初に記事にアクセスしたときに、ブラウザが画像を読み込んでしまいます。
しかし、srcを空にすれば画像は読み込まれません。

そこで、先ほど紹介した Javascript で、imgタグ内の lazy というクラス名を検索し、スクロールポイントを検出して、しきい値に入ったら、そのタグ内の data-src の URL を src の URL に差し替えて、画像を表示させているという動作のようです。
よく考えられていますね。

ただ、src に画像 URL が無いということは、Google bot の検出や SEO に影響が出るかも知れません。
良く分からないので、しばらく使ってみるしかないですね。

Youtube 埋め込み動画のオフスクリーン遅延読み込み

画像だけでなく、Google PageSpeed Insights で Youtube 埋め込み動画が遅いと警告されたので、画像と同じようにオフスクリーンの遅延読み込み対策をしてみました。

幸い、画像と同様に Intersection Observer が利用できたので、以下のようなスクリプトを footer の前(</body>の直前)に置きました。

ただ、これが正しいかどうかは私には分かりません。
とりあえず問題無く動いているようなので使っています。

これを使っても当方では責任は負えませんのでご了承ください。

<script src="https://polyfill.io/v2/polyfill.min.js?features=IntersectionObserver"></script>
<script>
  document.addEventListener("DOMContentLoaded", function() {
    var iframeLazyImages = [].slice.call(document.querySelectorAll("iframe.iframe_lazy"));

    if ("IntersectionObserver" in window) {
      let iframeLazyImageObserver = new IntersectionObserver(function(entries, observer) {
        entries.forEach(function(entry) {
          if( entry.intersectionRatio > 0 ) {
            let iframeLazyImage = entry.target;
            iframeLazyImage.src = iframeLazyImage.dataset.src;
            iframeLazyImage.classList.remove("iframe_lazy");
            iframeLazyImageObserver.unobserve(iframeLazyImage);
          }
        },{ root: null, rootMargin: "0px 0px", threshold: [0.0] });
      });

      iframeLazyImages.forEach(function(iframeLazyImage) {
        iframeLazyImageObserver.observe(iframeLazyImage);
      });
    } else {
      // Possibly fall back to a more compatible method here
    }
  });
</script>

image の場合と殆ど同じで、Youtube動画埋め込みタグ用の iframe 用に替えただけです。
最初の行に非対応ブラウザ用の Polyfill スクリプトがあります。

実際に貼り付ける際には、無駄な空白を削除して minify化した方が良いと思います。

埋め込み HTML タグは以下の感じです。

<iframe class="iframe_lazy" src="" data-src="Youtube video URL" style="position:absolute;top:0;left:0;width:400px;height:225px" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
<noscript><iframe src="Youtube video URL" width="400px" height="225px" frameborder="0" allowfullscreen="allowfullscreen"></iframe></noscript>

この場合は、<noscript>タグを入れて、非対応ブラウザ対応もしてありますが、Polyfillがあるからいらないかも知れません。
よくわかりませんので、とりあえず入れてあります。

これらを実装したテストページを作ってみたので以下のリンクを見てみて下さい。

https://www.mgo-tec.com/test01

このページの後半は Amazon リンクも Intersection Observer 化してあります。
(これについての作成方法は今回は紹介していません。)

このページをスクロールする前に、ブラウザ のデベロッパーツール(開発者ツール)を開いて、ネットワークタブを見てみてください。
スクロールすると、画像の出るところで読み込み開始していることが分かると思います。

因みに、ブラウザの拡張機能でセキュリティーソフトや Google Analytics オプトアウト、Google Publisher Toolbar などをインストールしていると赤い警告表示が出ますので、解除しておいた方が良いと思います。

ただ、全て解除しても、Google Chrome の場合、Youtube動画が表示されるときだけコンソール画面に黄色で以下のメッセージが多量に出ます。

[Violation] Added non-passive event listener to a scroll-blocking 'touchstart' event. Consider marking event handler as 'passive' to make the page more responsive.

黄色いメッセージなので、大きな問題はありませんが、要するにスマホなどでスクロールする時に、スクロールが一時的に停止されるから対策を摂りなさいと警告してくれています。
これの解決は残念ながらできませんでした。
ただ、Firefox では警告が出なかったので、私的には今回はヨシとします。

こうやって、実際に Intersection Observer を使ってみると、単なるスクリプトの貼り付けだけで実現できてしまうので、意外と簡単でしたね。
さすが、Google 先生のおっしゃる通り、ものすごい効果的な方法です。
これは、さすがにスゴイなぁと思いましたネ!

これで、PageSpeed Insights の評価がグーンとアップしました。

その他の対策

以上の対策で、全画像と Youtube 埋め込み動画のタグを入れ換えたおかげで、アクセス速度がかなりアップしました。
それに加えて、プラグインの Amazon Associates Link Builder を使うのをやめて、Amazon リンク画像も Intersection Observer 化しました。
これはなかなか良い対策だと思いました。
Amazon 画像が意外と数が多く、厄介なんですよね~・・・。
これの方法は、今回は紹介しておりません。
紹介するにはとっても骨が折れるし、そして現在とっても多忙なので、リクエストが多くあった場合には紹介しようとは考えています。

また、この他、ザっと以下の対策をしました。

●フォントやCSSを preload 読込み
●一部画像の WEBP 化
●CSS の最適化
●ショートコード自作
●プラグイン使用の削減
・・・

などです。
ここ1か月間、いろいろ対策をしました。

結果、PageSpeed Insights の評価で、パソコン用とは70~80付近まで上げられました。

モバイル用途だけは未だに遅いですが、体感的にかなりスピードアップできたので、概ね満足です。

私の今の能力ではここまでが限界です。

まとめ

ここ1か月の間、Flickr からの画像移行と、文字を消してしまったトラブルから復旧させる作業で、いい加減「うんざり」していました。
でも、Web開発についていろいろと見えてきました。

Google PageSpeed Insights が急に厳しくなって、「やってられね~!」と思いました。
ですが、実際に対策を施してみると、Google先生のおっしゃる通り、素晴らしく良好な結果が得られました。

そして、パソコン用の画像や動画を多量に貼った Web ページでも、モバイル用途の AMP ページと同等のアクセス速度が叩き出せるということが分かったのは収穫です。
なるほど、Google 先生は世界の全 Webページを高速化させたい意図が少し分かった気がします。

そして、今回、Amazon API に手を出して、プラグインを使うのをやめて Intersection Observer 化したのは、我ながら収穫でした。
これを応用すれば、IoT 電子工作で生かせそうな気がしてきました。

ということで、今回はここまでです。

前から申し上げていたように、今年は本業の割合が増えて超多忙になっています。
記事更新の頻度が極端に減ると思いますが、これからも何卒ご支援いただけると幸いです。

スポンサーリンク


Amazon.co.jp 当ブログのおすすめ
Amazon.co.jp
M5Stack Basic
スイッチサイエンス
Amazon.co.jp
ESPr Developer 32
スイッチサイエンス(Switch Science)
Amazon.co.jp
Amazon.co.jp

コメントを残す

メールアドレスが公開されることはありません。

*画像の文字を入力してください。(スパム防止の為)

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください