海岸製作所

Blog

2019
1
30

lazyloadをIntersectionObserverに書き換えてレンダリングブロックを緩和する



会社でgoogleスピードテストの評価を少しでも上げたいと。

じゃぁこうしましょうと…

スクロールに追従して、画像の遅延ロードといったことを行いたいが、

このようなケースにおいて、今まではスクロールイベントをフックとして実装することがほとんどでした。
しかし、頻繁に実行されるスクロールイベントは、ブラウザにとって優しい処理とは言えず、特にスマホではスクロール詰まり(Scroll Jank)を引き起こしてしまうこともありました。
やるんだったら、パフォーマンスも改善したい…。

Intersection Observerとは
その名の通り「Intersection(要素間交差)」を「Observe(監視)」するAPI。
任意の要素(DOM)同士の交差を監視することが出来ます。
デフォルトでviewport(見えている範囲)とある要素が交差=ある要素が見えたら何かする、というものです。

スクロールイベントをフックするよりパフォーマンスも改善できそうだ
そんなわけで、手始めにIntersection Observerを使って画像の遅延ロードをしてみようというのが今回の趣旨です。

lazyloadの弱点

画像の遅延ロードをさせるには真っ先にlazyloadが思い浮かびました。
同じ仕組みでIntersectionObserver対応に書き換えようと思いましたが、
lazyloadにも弱点はあります。
▪️lazyloadの弱点▪️
1)画像のパスをdeta-属性に書かなければならず少し面倒。
2)JSがなんらかの理由で動作しなかった場合、画像が一切表示されない。
3)だからインデックスでも隙が。

なので、原理はlazylordと全く同じだけども複数人で運用やってる以上は、組み込みは楽にしたい。
imgタグはそのままでコーディングには影響しない仕組みにしようと思いました。

具体的には、ページが読み込まれる前に全てのimgパスを取得し、deta-属性に代入しつつ同時にダミー画像に一旦置き換え。
最後にlazyloadと同じようにウインドウ内に入ってくる画像から、元の画像に復帰といった具合。

そうするとJSの発火のタイミングが重要になってきます。

読込みのタイミング

よくJSで使うのはwindow.onloadだとかfunctionや$(document).readyだけど、
画像のパスを満遍なく拾う関係上、確実にDOM生成された瞬間に発火させたいんです。
調べるとDOMContentLoadedっていうイベントハンドラがあったので最初の一行はこうなります。

画像のパスを取得してダミーの画像に置き換える

ここからは実際のlazyloadの処理を行う前の下準備。
画像のパスを取得してダミーの画像に置き換えるまでです。
これをすることでhtmlのコーディングを通常通り行えば良いのでlazyloadの弱点が一つ解消されました。

Intersection Observerで交差監視

いよいよここからが本丸。
Intersection Observerで要素がウインドウ内に居るか監視をして
ウインドウ内に来たら”画像のURLを元に戻す=画像読み込み”という工程部分です。
こちらを参考にさせていただきました。
https://firstlayout.net/animation-on-elements-entered-on-the-screen/
これで、スクロールイベントもさようならです。

注意しなきゃならない点

本記事掲載時点でIntersection observer に対応しているブラウザは、 Chrome ・ Firefox ・Edge です( iOS 版はいずれも未対応)。
Can I use… : IntersectionObserver

ただし、対応していないブラウザでも Polyfilを読ませることで動作します。

ソースコード(フル)

役割毎に説明したソースコードを合体させるとこんな風になります。

Category カテゴリ一覧

Author このブログを書いてる人

ハヤシ ヒロキ

2009年からWeb製作屋やってます。
葉山育ち。
お酒とアクアリウムと鉄道が好きな30代。
どちらかと言えばデザインよりもコーダー寄り。
表現の幅を広げたくてインタラクティブなものやシステム的なものも取り入れるべく悪戦苦闘。
シンプルで動きなど触っておおっとなるWeb制作を目指しています。
お仕事もお待ちしております。

お問い合わせはこちら