営業用サンプルLPが19MBでデプロイされていた話
副業のHP改修事業で、営業先に見せるサンプルLPを Claude Code とAIで作っている。
そのうち1つを Cloudflare Pages にデプロイしたあと、何気なくファイルサイズを確認して凍った。
19MB。
1ページのHTMLファイルが、19メガバイト。
19MBの実害
光回線で見ると、体感0.1秒未満で開く。重いという感覚すらない。
でも、営業先がスマホで開いたらどうなるか。
- 4G の格安SIM、混雑時間帯:20〜60秒待ち
- 3G エリアや電波の弱い場所:数分〜タイムアウト
- ギガが残りわずかなSIM:開いた瞬間に容量を食い潰す
私の営業先は、地方の士業の先生(50〜60代)。外出先のスマホで開く可能性は低くない。
「ローディング待ちで閉じられる」が一番ありえる。営業の入口でこれは致命的。
私のミス
デプロイ前に du -sh を打っていなかった。
「AIが書き出してくれたHTMLをそのまま上げる」しかしていなかったので、サイズを気にする発想自体がなかった。
普段なら数十KBで済むものが、何かのはずみで19MBになっていたら、普通は気づく。でも今回は気づかなかった。
理由はもう1つあって、私がサンプルを確認するときの環境が、自宅の光回線+PCだったから。
光回線で見ると、19MBのページも体感0.1秒未満で開く。「ちょっと重いな」とすら感じない。
これが家の外で、スマホで開いていたら一発で気づけたはずだ。「いつまで経ってもロード終わらない」とイライラしながら待つことになるから。
作る側の環境と、見る側の環境が違う。これを忘れていた。
19MBの正体
不思議だったので分解してみた。HTMLの構造は3つに分かれていた。
- 18.5MB:JSONで書かれたアセット一覧
- 558KB:本体のHTML文字列
- 6KB:起動スクリプト
JSONの中身は何かというと、249個のファイルが入っていた。内訳は248個のフォントファイルと、1個のPNG画像。
それぞれが base64 という形式で、文字列に変換されて詰め込まれていた。
ブラウザでページを開くと、起動スクリプトが「JSONからフォントと画像を取り出して、HTMLに差し込む」という動作をする。つまり全部が1ファイルで完結している、オフライン動作する仕組みだった。
これは AI のArtifact機能(HTMLをパッと書き出してくれる機能)の標準的な書き出し形式らしい。便利な機能だけど、本番に上げるには重すぎる。
なぜフォントが248個もあるのか
これも調べた。
日本語フォント(Noto Sans JP・Noto Serif JP)は、文字数が多いのでファイルが大きい。Google Fonts は「漢字ブロックごとにファイルを分割しておいて、ページが使う文字に必要な分だけダウンロードする」という工夫をしている。
その分割数が248個。
普段は Google Fonts の CDN(配信サーバ)からブラウザが必要なものだけ取りに行くので、ユーザーが248個全部をダウンロードすることはない。
ところが Artifact の standalone 書き出しは、248個全部をHTMLに入れてしまう。「オフラインで動かしたい人」を想定した仕組みだから。
解体と最適化
3ステップで解体した。
- JSONからアセットを取り出して個別ファイルにする
- 248個のフォントは全削除して、Google Fonts CDN へのリンクに置き換える
- PNG画像(1.6MB)を WebP(42KB)に変換する
WebP は Google が作った画像形式で、JPEGより圧縮率が高い。Pillow(Pythonの画像ライブラリ)で1行で変換できる。
ヒーロー画像は1672×941ピクセルあったので、表示に必要な1400ピクセルに縮小もした。
結果は、19MB → 75KB。99.6%減。
営業に間に合った
このサンプルは、別の士業先生(こちらは初回営業中)への送付用ではなかったが、別案件の最適化作業にも応用が効いた。
すでに営業メールを送ってしまった案件のサンプルLPも、同じパターンで重かった。ヒーロー画像が1.88MB、トラック写真が1.30MB。両方ともAIが書き出したPNGをそのまま上げていた。
メール送信の数時間後に気づいて、急いで最適化+再デプロイ。営業先がアクセスする前にギリギリ間に合った。たぶん。
学んだこと
- AIが書き出してくれたHTMLは、本番に上げる前に必ずサイズを確認する
du -sh .で1コマンド、これを儀式にする- 画像はPNGのままにしない。WebPに変換する1行で十分
- 「便利機能」と「本番運用」は別物。間に1ステップ確認を入れる必要がある
- 自分が見ている環境と、相手が見る環境を一致させる。光回線+PCで作ったものを、4Gスマホで見直す
AIが速いと、確認をスキップしたくなる。スキップした分のリスクは、本番に出してから返ってくる。
まとめ
- 営業用サンプルLPが19MBになっていて、スマホで数十秒待ちだった
- 自宅の光回線+PCで確認していたから気づかなかった。家の外でスマホで見ていたら一発で分かった
- 正体はAIが書き出した standalone HTML。248個のフォントと画像が base64 でJSONに詰め込まれていた
- 解体してCDN置換+WebP化で 19MB → 75KB(99.6%削減)
- デプロイ前に
du -shを打つ儀式を作った
便利だからといって、確認まで省いていい理由にはならない、という当たり前を再確認した。