症状: 見た目は正常、転送量だけが異常だった
コラム記事のサイドバーに、閲覧数上位5件のサムネイルを出すブロックがあります。表示サイズはCSSで72×72pxに固定してあり、見た目上は崩れていません。
全ページを機械走査したとき、このブロックの転送サイズだけが目に留まりました。5枚合計で1,428,787バイト(約1.4MB)。うち1枚は931KBのPNGでした。
72pxの正方形サムネイル1枚に900KB超は明らかに異常です。
真因: image styleを経由せず原本URLを生成していた
該当のブロックのコードを追うと、画像URLの生成にDrupalのfileUrlGeneratorを直接使っていました。
// 是正前: 原本ファイルのURLをそのまま生成していた
$img_url = $this->fileUrlGenerator->generateAbsoluteString($uri);
fileUrlGeneratorはファイルの実体URLをそのまま返します。リサイズも圧縮も一切しません。 アップロード時の元画像がそのまま配信されていました。
Drupalには表示サイズに応じて画像を変換する仕組み(image style)が別に用意されています。しかしこのブロックは、その仕組みを経由していませんでした。
なぜ気付きにくいか: CSSが先に問題を隠していた
このバグが長く気付かれなかった理由は、表示上は何も壊れていなかったことです。
.item-image {
width: 72px;
height: 72px;
}
CSSが表示サイズを72×72pxに固定していたため、原本画像がそのまま埋め込まれていてもレイアウトは崩れず、レイアウトシフト(CLS)も起きません。見た目のスクリーンショットを何度撮っても、この問題は写りません。表示を確認するだけの検証では、原理的に発見できないバグでした。
問題は見た目ではなく、ブラウザが裏で931KBのPNGをダウンロードしてから72pxに縮小して表示していたことです。転送量とレンダリングコストの両方を無駄にしていました。しかも本ブロックはコラム全71ページのサイドバーに出るため、累計で約97MB相当の無駄な転送になっていました。
是正: image style経由に統一する
表示の2倍サイズ(Retinaでも粗くならない144×144px)で、1:1にクロップしてwebpへ変換するimage styleを新設しました。
name: sidebar_thumbnail_144x144
effects:
image_scale_and_crop:
width: 144
height: 144
anchor: center-center
image_convert:
extension: webp
URLの生成をこのimage style経由に切り替えます。
// 是正後: image styleのbuildUrl()を経由する
$style = $this->entityTypeManager->getStorage('image_style')->load(self::THUMBNAIL_STYLE);
$img_url = $style
? $style->buildUrl($uri)
: $this->fileUrlGenerator->generateAbsoluteString($uri);
image styleが読み込めない異常時は、あえて原本URLへフォールバックする設計にしました。画像が消えるより、多少重くても表示され続ける方がましだからです。<img>タグにもwidth・height・decoding="async"を明示し、ブラウザがレイアウト計算を先に済ませられるようにしました。
是正後の転送量は5枚合計で22,874バイト(約22KB)。98.4%の削減でした。
このimage styleは、リサイズ(144×144pxへの切り抜き)と形式変換(webpへの変換)の2つの効果を同時に持たせています。どちらか一方だけを分離して効果を測ってはいませんが、表示サイズと配信フォーマットの両方を実態に合わせて初めて、この削減幅になったという点は変わりません。
deploy後の注意: 派生画像は初回アクセス時に生成される
image styleの派生画像は事前に作られているわけではありません。最初にそのURLへアクセスがあった瞬間に、Drupalがその場で生成して保存します。 それまでの間、リクエストはリダイレクトを経由します。
事前に生成しておきたい場合は、対象の全ファイルURIに対して派生生成の処理を明示的に走らせる必要があります。デプロイ直後の最初のアクセス者だけがこの生成コストを負う、という点は覚えておく価値があります。
まとめ
- 表示サイズをCSSで固定しても、転送しているファイルそのものが軽くなるわけではありません。CLSは防げても帯域は無駄になります
- 画像URLの生成には必ずimage style(またはそれに相当する変換の仕組み)を経由させてください。
fileUrlGeneratorが返すのは常に原本です - 見た目の検証だけでは発見できないバグがあります。 レイアウトが正しいことと、転送しているファイルが適切なサイズであることは別の観点です
- image style経由への切り替えは、異常時に原本へフォールバックする設計にしておくと安全です。「画像が消える」より「重いが表示される」方を選びました
- 派生画像は初回アクセス時に生成されます。デプロイ直後にまとめて生成しておきたい場合は、その処理を明示的に走らせてください

