de:code2020の感想記事が書きかけなんで更新しづらいんだけども、書いとく。

対象読者は…謎だな。誰向けにも書いてない。インターネットのすげー基本的なことからいちいち書いてるから、技術者向けですらない。なんかの読み物だ。今日は俺、書きたいことを書くんだ。

去年から今年(2020年)あたりにブラウザに組み込まれたlazy loadについて。インフラもバックエンドも好きなんだけどWebもカオスで趣深いよね。

◆結論(読まんでよし)

Lazy loading | MDN

Lazy loading via attribute for images & iframes | Can I use

安心と信頼のMDN&Can I use。IEとSafariは未対応っぽいね。カス。

Intersection Observer API | MDN

Lazy loadingは根本的にはコイツをラップしてくれてんだろうな。「事態は完全に酷くなりえます。」って表現がなんか好き。「ヤバみが深い」と同意語の関係にあるだろう。

調べていくとどうやらIntersection Observer V2ってのもあって(略

しょうもねぇことまで話すから玄人は上記ページを開いてこのブログをクローズし、脳をFLUSHしてゲラウトヒアです。巣に帰れ。

◆代表あいさつ

侍エンジニア塾HTMLクイックリファレンスTECHACADEMYテメーらクソうるせぇんだよ検索結果に載ってくんじゃねぇカスボケ。田島メンター!!お前は死ね!!

UX MILKWWWクリエイターズはなんとなく許す。

GoogleくんはオメーMDNを先頭にもってこい。

◆インターネット

うん。まず、インターネットは文字通りネットワークであるわけだから、お前さんがインターネットブラウザを介して見ている文字や映像なんかはそのネットワークを通してどっかからか提供されている。

「どっかからか」っていうのは、サーバーと呼ばれるマシンが世界のどっかにあって、それ。そのマシンとオメーの携帯やらパソコンはつながっている。電磁的に辿れる。…という表現が適切であるかどうかは知らないです。

日頃インターネットをウロウロしてると、画像の掲載されているページを頻繁に目にすることと思う。その画像もどっかのサーバーに乗っているデータです。

Webページってその…お前らがどういう想像しているんだか今や分からねぇけど、積み木みたいに要素をドラッグドロップして組み立ててページ作ってるわけじゃないんです。全部文字で表現してる。具体的に言や「HTML」と「スタイルシート」「スクリプト」の三要素がだいたいです。

サーバーとの間でそれら文字情報をやり取りしてブラウザくん(ChromeとかInternetExplorerとかFireFoxとかSafariとか)が文字を解析し、見えるように描画をしてくれるです。

※下のやつは、適当にボタン押しても特に大変なことにはならないから色々みてみるがいいよ。文字情報によってページが作られていることを読み取れるかもしれない。

See the Pen  mdVxpvw by 10baceInsider (@connect-a) on CodePen.

かたや画像はテキストっていうか寧ろ0と1の羅列みたいになってて、それを人間がみてオナるための画像にするのもブラウザくんがやってくれる。例えば01の並びでピクセルの持っている色の情報と場所を表現できればそれを集めて画像にできるだろ。例えばな。

ってかピクセルって言って通じるんだろか。画素って言えば良いのか。

※余談:画像を表現する方法には種類がある。jpegとかgifとか。はたまた、このブラウザのトップ画像みたいにテキストベースの(01じゃない)画像もある。
ブラウザだけが画像を表示できるわけではなくて、0と1を画像にするルールは世界的な取り決めでなされる。決まりがあるからiOSでもWindowsでもLinuxでも同じ画像データを表示できる。各デバイスで画像を表示するための処理を実装しているのだよ。

◆余談:パッケージング

いまどき、素でHTMLやらCSSやらJavaScriptやら書いてるやつぁいねぇ。阿部寛くらいじゃねぇかな。というのも、普通にやってたら収集つかなくなるんですね。管理不能になる。だから、書きやすく、管理しやすく書いたらバンドラにそのソースコードを食わせてHTMLとCSSとJSを吐き出してくれるように頼めばいい。そういう世界。

でもその世界も自分でwebpack環境構築してgitignore書いてってちょっとしたhell(ぢごく)なので、いまやキーボードをちょっとカタカタいわすだけで環境できちゃう世界も到来している。Vue CLIとかね。でもVueもお作法っていうか「ここ縛らないで自由にやると死ねる」みたいなこともあったりで(略

ちなみにA collection of .gitignore templatesってのがgithubから提供されてて(略

なんにせよJavaScriptが滅ばない限り地獄です。俺は地獄に足場を見つけてルールを作ってそこで涙を流しながら死んだ世界を眺めています。

◆画像表示問題

お前が例えばエロ画像お絵かき同人サイトを作成したとする。画像がメインのサイトであるわけだから、ページには画像が並ぶ。それら画像を表示する際の戦略を考えよう。

まず一番単純なのは、「ページを開いたときにそのページの画像全てを描画してしまう」という戦略。ここでいってる描画ってのはつまり、

  1. ページを開いたとき、そのページに画像のURLが埋め込まれていたとしたら
  2. お前の立ち上げているブラウザ(クライアントと呼ぶ)は画像を持ってるサーバーに対して「画像ください」して
  3. サーバーが「いいよ。あげる。」して
  4. サーバーから画像のデータが転送されてきて
  5. お前のブラウザが0と1の並んだデータを読み込んで
  6. 画像を表示する

の一連の流れ。

それを、ページに載ってる全部の画像でやる。

これには色々問題がある。

まずもってお前の描くエロ絵ってリョナありゴアあり欠損ありのありありでやっばい趣味丸出しであるわけだから、訪問者は九分九厘、秒でブラウザバックする。だのに全部の画像をサーバーにリクエストしたり描画したりするのはエコじゃないじゃないじゃない。ギガが減るのは嫌だろ。電池が早く減るのも嫌だよなぁ。

そこへんに対するソリューションとして「遅延読み込み」を適用する。

◆遅延読み込み

大石ゆかり「田島メンター!!遅延読み込みってなんですか~?」

???「これはな、お前を気持ちよくするものだよ。」

~完~

っていうのでlazyなloadをしてみようという話になってくる。lazyは怠惰。loadは読み込み。怠惰な読み込み。遅延読み込み。

今回の例で言えば、ブラウザが今見ている範囲外について画像の読み込みをサボればいいじゃない。という話になるんじゃないか。その範囲が見えたときに読み込む。

それは、どうやして実装したものだろうか。(こっから先はちょっと技術)

◆Lazy loading

Webページ全体の範囲と、ブラウザが現在見せている範囲があるな。その「ブラウザが現在見せている範囲」をviewportという。

また、お前のゴアい画像も画面上で占める範囲を持っているだろう。

その範囲と範囲の交差を監視するためのAPI(アプリケーションプログラミングインターフェイス)こそIntersection Observer APIです。

※APIってのは、ブラウザくんが「これお前のプログラムの中で使ってもいいよ」ってしてくれているインターフェースです。ブラウザの持っている機能を使わせてもらうための口みたいなもの。APIはブラウザだけにある概念ではない。パソコンにもあるしOSにもあるしインターネット上にもあるし。

そのIntersection Observer APIをごちゃごちゃいじって画像の遅延ロードを実現できるんですね。

っていうのが、クッソ実装面倒だった。めんでぇって思ってたらブラウザ標準のLazy loadingがきました。マリガトー

See the Pen  vYLjpJO by 10baceInsider (@connect-a) on CodePen.

はい。imgという要素がHTMLの中に並んでいることと思うんだが、そこに「loading="lazy"」という属性が指定されておるでしょう。これだけでもう遅延ロードできます。しゅ…しゅごい…///

F12で開発者ツール開いてNetworkタブをみると、たしかにiframeのviewportに画像が交差するまでロードされてない。おっp…おっぱげた…!

▼注意点(読まんでよし)

・高さ

CSSでimgタグにheight指定してるっしょ?それ指定しないと画像サイズが確定するまで要素の高さが0であるわけだから、HTMLがレンディングされた瞬間に全img要素が交差してるもんでロードされちゃうよね。

imgに直で高さ指定はちょっと破廉恥だから、親要素の高さをどうにかするとかしろ。

・遅さ

このCode PenではLorem Picsumっていう適当な画像を返してくれるAPI使ってて、見てとれるくらいロードが遅い。今回は寧ろロードされているさまがわかるから説明に都合がいいんだけど、本来は画像をCDNに撒くとか工夫してロード時間を短縮するべきでしょうね。じゃないと訪問者に空白を見せてしまうことになる。ロードされるタイミングいじるとか細かい制御すんならIntersection Observer API叩くしかねぇぜ。アレはアレで分かりづらいけど多機能ではあるから、何が実現できるかってことは知っておいてもいいだろうよ。

もしアレなら読み込み中にローディングスピナーかなんかを表示しておくのもいいだろう。jsでimgのsrc属性をいぢることになるけど。これもplaceholderみたいな感じでブラウザ標準になってくれねぇかな。

◆余談:投機読み込み

投機読み込みというコトバは俺がいま適当に作っただけなんだけど、「投機的実行(speculative execution)」という考え方がある。用語としてはどっちかっていうとハードウェア向きの、CPUの話になるんだが、考え方は別にCPUにしか適用できないって類のもんじゃない。

たとえば、ゲームで遊んでてセーブ画面に入ったとする。セーブ完了したらゲームに戻る可能性が高いじゃん?だからセーブ画面に入った瞬間に裏で次のステージをロードしとけばいいじゃん。セーブ完了してからモタモタロードしてんのはダサい。

っつーので、ブラウザの画像については、「今描画に使っていないけどすぐに使う画像」を裏でロードしとけばいいじゃん。

それは「rel="prefetch"」でだいたい解決できる。ちゃんとキャッシュすればいちいち画像を取りに行かんでもブラウザに読み込んでおいたのを持ってくるだけでいい。余談だし多くは語らんが。

リンク先読みの FAQ | MDN

wasmのライブラリを事前ロードしておくなんてのもあり得るだろう。dns-prefetchっつー名前解決を事前にやっておくやつもある。ふははははは。ふははははははははは。

あと、画像だけじゃなくバンドラで砕いたchunk.jsどもを選んでロードしておくとかね。それやるならまた色々と設定を(地獄

◆結論

ブラウザの標準がどんどん進化していて不亦説乎

進化が速いから弄ばれてる感あるけど楽しいっちゃ楽しいですよはい。