18MBのブラウザゲーム画像を世界観を保ったまま軽くする
PNG・WebP・遅延読込を実データで比較
背景:原本を失わずに配信だけ軽くする
『60秒後の彼女』は濃いグラデーションと赤い光沢を持つ世界観を持つ。その原本PNGは約18MB(11ファイル)。これを単純に「圧縮して上書き」すると、後から世界観を修正・差し替えするとき原本が失われる。そこで source(原本)と delivery(配信)を分離した。
assets-source/*.png:ロスレス原本。Gitで保全し、ビルド出力には含めない。assets/*.webp:配信用(quality 90)。PNGフォールバックも併置。
before / after(実測)
| Asset | PNG (KB) | WebP (KB) | 削減 |
|---|---|---|---|
| breathing | 1745 | 100 | 94% |
| clear-bg | 1730 | 74 | 96% |
| exploration | 1631 | 94 | 94% |
| gameover-bg | 1581 | 42 | 97% |
| phone | 1703 | 89 | 95% |
| play-bg | 1600 | 57 | 96% |
| prologue | 1677 | 89 | 95% |
| result | 1737 | 104 | 94% |
| title-bg | 1540 | 40 | 97% |
| title | 1632 | 100 | 94% |
配信WebP合計は約 791 KB(元PNG比 約95%削減)。初期要求する背景4枚のWebP合計は約213 KB。
なお「リポジトリサイズ」は原本(source)を含むため18MBのままだが、転送(delivery)はWebP であり、ユーザーがダウンロードするバイト数は劇的に減る。これが「repository size」と「transfer size」の違いだ。
フォーマット対応とフォールバック
WebPは Chromium・Firefox・Safari 14+ でサポート。それ以前のブラウザのため、CSSでは image-set() で WebPを優先し、非対応時は PNGへフォールバックする:
.title-bg {
background-image: image-set(
url("./assets/title-bg.webp") type("image/webp"),
url("./assets/title-bg.png") type("image/png")
);
}
これで「古いブラウザで404になる」ことを防ぐ。upload/ には WebP と PNG の両方を含める。
視覚品質の確認方法
圧縮率だけで「画質が保たれた」と断定しない。本作は Pillow 既定エンコード(quality=90, method=6)を用い、濃いグラデーションのバンディングや赤い光沢のエッジを目視確認した。数値(PSNR/SSIM)だけでは主観品質を保証できないため、目視を併用している。
build スクリプト
生成は決定的:同じsource PNGからは常に同じWebPバイトが出る(固定パラメータ)。npm run gen:delivery で assets-source/ から assets/ を再生成する。孤立資産(参照されない ui-mock)は delivery から除外し、source のみに留めた。
制限(limitations)
- Lighthouse は使用していない。転送量は実バイト数で評価した。
- AVIFは今回生成していない(PC負荷と効果のバランスでWebPに集中)。将来のブラウザ対応拡大時に再評価可能。
- 視覚品質は自動指標だけでなく目視確認に依存している。