Playwrightで画面外のloading=’lazy’な画像もscreenshotに含める
2023/02/27
最終更新:2023/04/12
imgタグにloading='lazy'
を指定すると画像読み込みをビューポートに入るまで保留してくれる(lazy loading)。これは一般的にパフォーマンスが上がるとされていて、Next.jsが提供するImageコンポーネントではデフォルトの機能として提供されている。
自分のブログにVRTを導入しようとPlaywrightを触っている際に、fullpageでscreenshotを撮ろうとするとlazy loadingな画像がscreenshotに含まれたり含まれなかったり、そもそもコンテンツ下部に画像があったりして読み込まれていなかったりして苦戦したのでメモ。
解決策
最下部までスクロールダウン→スクロールトップ
原始的だが確実。Playwrightのメンテナも言っている。
やっていることはdocument.body.scrollHeight
の値を見ながらwindow.scrollTo
によるscrollを行っているだけである。
await page.evaluate(async () => {
const delay = (ms: number) =>
new Promise((resolve) => setTimeout(resolve, ms))
// scroll to bottom
for (let i = 0; i < document.body.scrollHeight; i += 100) {
window.scrollTo(0, i)
await delay(50)
}
// scroll to top
for (let i = document.body.scrollHeight; i > 0; i -= 100) {
window.scrollTo(0, i)
await delay(50)
}
})
await expect(page).toHaveScreenshot({ fullPage: true })
delayを少しかけることでsmooth scrollを表現している。100や50という数字はテストの実行速度に影響するので必要に応じてチューニングする。
このdelayはevaluateのコールバック内で宣言しないとReference Errorになる。
page.mouse.wheel
でもスクロールできるが、一部サポートがないAPIなのでwindow.scrollTo
のほうがよさそう。
全体的なサンプルコードはこちら
lazy loadingを使わない
例えばこの記事では画像を記事全体に渡って載せていて、少し早めのスクロールをすると画像読み込みが間に合わずちらつきが発生する(チューニングしろという話ではある)。SSGやISRを行っている時点で個人ブログ程度であれば一定のパフォーマンスは出るので、lazy loadingをやめても実は支障がないかもしれないし、ちらつきが発生しない分ユーザー体験は上がるかもしれない。このブログも検証次第ではlazy loadingをやめるかも。
参考
https://developer.mozilla.org/ja/docs/Learn/HTML/Howto/Author_fast-loading_HTML_pages#画像の遅延読み込みを使用する
https://developer.mozilla.org/ja/docs/Web/API/HTMLImageElement/loading#値