picture 要素もちゃんと Preload Scanner が動くのでどんどん使っていこう
先日、このツイートを見た。
画像のサイズを変えてもパフォーマンスは改善されない、というのは同意できるが、2番目の「picture
タグによる画像出し分けは、Preload Scanner が効かない~」について疑問が残る。果たして本当に picture
要素は Preload Scanner が効かないのだろうか。
Preload Scanner とは
Preload Scanner (プリロード スキャナ) は、ブラウザが HTML を DOM としてパースする前に、簡易的なパーサーを使用してウェブページに必要なリソースを事前にダウンロードする (プリロードする) 仕組みのことだ。これは HTML の仕様ではなく、あくまでもブラウザが独自実装しているものであるが、大抵のブラウザにこの機能が備わっている。
script
要素や img
要素などによるリソースの読み込みがプリロードの対象なのだが、例えば document.createElement
で img
要素をつくって DOM に挿入するといった JavaScript コードによるリソースの読み込みは、Preload Scanner が検知することができない (JavaScript を実行するまでリソースを読むべきか分からないから)。
Preload Scanner を無効化する
Chrome 125 からは、Chrome の起動する際に渡すパラメーターに --enable-features=SkipPreloadScanning
を追加すると、Preload Scanner を無効化することが可能である。今回はこれを検証に使う。
本当に picture 要素は Preload Scanner が効かないのか
https://labs.aioilight.space/responsive-image/picture-tag.html
このページを用意した。
<picture>
<source srcset="sp.webp" media="(max-width: 480px)">
<img src="pc.webp" alt="野良猫の写真。">
</picture>
このような picture
要素が挿入されている。
![Preload Scanner が無効の Chrome のパフォーマンスプロファイラ。](https://wangel.aioilight.space/wp-content/uploads/2024/07/disabled-chrome-600x167.webp)
Preload Scanner を無効化した Chrome でパフォーマンスを見てみる。HTML が返却された後、HTML のパースが始まり、DOMContentLoaded
の直前で pc.webp
へのリクエスト送信が始まる。このことから、DOM の構築中に picture
要素を解析し、ダウンロードすべきリソースを決定してダウンロードしようとしていることが分かる。
![Preload Scanner が有効の Chrome のパフォーマンスプロファイラ。](https://wangel.aioilight.space/wp-content/uploads/2024/07/enabled-chrome-600x153.webp)
次に、Preload Scanner が有効なふつうの Chrome でパフォーマンスを見てみる。HTML が返却された後、HTML のパースが始まる前に pc.webp
へのリクエスト送信が始まる。このことから Preload Scanner によって picture
要素の画像がプリロードされていることが分かる。
追加情報
whatwg の Preload Scanner 標準化についての issue で、Chrome の Preload Scanner の挙動についてのコメントがある。
PreloadScanner logic got more and more complicated over time. For example, it simulates the media query match so that it won’t request images of the wrong resolution.
Preload Scanner は高速なパーサーであるものの、間違った解像度の画像をリクエストしないよう「メディアクエリのシミュレート」をするなど、複雑化している、と書かれている。
この記述は、間違いなく picture
や img
要素の srcset
属性の話だろう。
まとめ
picture
要素も Preload Scanner が動くので、どんどん picture
要素を使っていこう。
ちなみに、単にメディアクエリで切り替えるだけでなく、
https://labs.aioilight.space/responsive-image/picture-tag2.html
このページのように、画面解像度に応じた画像ファイルの選択といった、少し複雑な記述でもちゃんと効いている。