目次5項目
ゆめさくです。このサイトを作っています。
ここ数日、広告の LP とスクールの HP、それから記事置き場の /lab を、React Router の SSR から Astro の静的な書き出しに移していました。その話をします。
料金ページの LCP が 10秒を超えていた
きっかけは PageSpeed Insights (PSI) の点数です。スマホで測ると、/lab の一覧が 55点、/women の料金ページは 41点でした。料金ページは一番大きな要素が出るまで (LCP) 10.8秒かかっていました。
広告から来た人は、待ってくれません。10秒白い画面を見せたら、ほとんど帰ります。
同じ広告の LP を、移す前と後でスマホ相当の条件で開いて並べると、こうなります。前の版は 3秒まで真っ白で、後の版は 1秒の時点でボタンまで出ています。

遅いのはサーバーではなかった
最初はサーバーを疑いました。でも測ると、HTML はキャッシュから 0.05秒ほどで届いていました。今日本番で測り直しても 0.05〜0.08秒です。
遅いのはブラウザの側でした。Google Fonts の和文の CSS が大きく、読み終わるまで文字が描かれない。そのうえ広告の LP は、ほぼ読むだけのページなのに、JS を 40本近く読んでいました。アプリ全体の React を丸ごと動かしていたからです。
ここで原因がサーバーだったら、キャッシュや問い合わせを直すほうが先でした。測ってから手を決めたので、作り替えに踏み切れました。
部品は触らず、書き出し方だけ変える
LP のデザインと文は、何度も直してきた資産です。書き直せば、どこかが必ずずれます。
なので部品は1つも書き直していません。Astro は React の部品を読み込んで、ビルドのときに HTML にしてくれます。ブラウザには React を送りません。数字のカウントアップや動画の遅延読み込みのような動く所は、部品に目印を付けて、素の JS で動かしました。
TypeScript
// 目印の付いた要素だけを、素の JS で動かす
document
.querySelectorAll<HTMLElement>("[data-countup]")
.forEach((el) => startCountUp(el));和文フォントは、最初の画面に出る字だけを切り出して自前で持つ形にしました。最初は「、」や「。」が漏れて、その字だけ端末の字で出ていました。いまは1字でも漏れたらテストが落ちます。
数字にするとこうです。

この手の点は測るたびにぶれます。同じページで 91点の次に 70点が出たこともあるので、3回測って真ん中を見ています。
1行で戻せるから、1ページずつ切り替えられた
全部を一度には移せません。ログイン中の画面や管理者の編集、フォームの送信は、今のアプリでしか動かないからです。
そこで、書き出した HTML を返す小さな Worker を前に置きました。書き出していない URL、ログイン中の人、編集モード、POST は、Cloudflare の service binding で今のアプリへそのまま渡します。

返すページは LIVE という一覧で決めています。
TypeScript
// LIVE に入れたページだけ、書き出した HTML を返す
if (!LIVE.has(url.pathname)) return env.APP.fetch(request);
return env.ASSETS.fetch(request);これがこの仕事のミソでした。1ページ足して、本番で確かめて、次を足す。おかしければ一覧から外して配備し直すだけで、今のアプリのページに戻ります。今のアプリ側のページは消していません。
戻しが1行だと、切り替えの判断が軽くなります。結局、広告の LP、HP、/lab、用語集まで、数日で順に切り替えられました。
壊していないことは、目ではなく機械で確かめた
LP で一番怖いのは、見た目より計測が壊れることです。広告のピクセルや LINE ボタンの記録が1つ欠けても、画面を見ただけでは分かりません。
そこで、本番の今のページと書き出した HTML を同じ広告のパラメータで開いて、文字の差、ボタンの位置、ページの高さ、送られる計測のリクエストを比べるスクリプトを書きました。移した7ページすべてで文字の差は 0行、計測のリクエストも同じでした。わざと計測の欄を壊して「差あり」と出ることも見ています。
それでも事故はありました。画像の住所を書き換える処理が単純な文字列の置換で、絶対の URL の途中まで書き換えてしまい、ロゴの住所が /women/women/ という存在しない場所になっていました。正規表現を直すだけでなく、書き出した HTML にその形が残ったらビルドを止める検査を足しました。直した場所ではなく、壊れた結果のほうを見張っておけば、次に誰がどこを触っても止まります。
もう1つ、配備直後の確かめがたまに落ちました。1秒以内だと Cloudflare の各所に新しい版が行き渡る前で、前の版が返ってくるのです。いまは 3秒おきに見て、60秒まで待つようにしています。
予約の暦のように中で動くものが多いページは、まだページごと React を動かしていて、軽くなりきっていません。動く所だけを切り出すのが次の仕事です。
相談
個別カウンセリング
受講を決める前に、オンラインで60分、人に相談できます。無料で、希望した人だけが予約する形です。
たとえば次のような相談です。
- 自分の生活 (仕事・家庭) で学習時間を確保できるか
- どの職種を目指すのがよさそうか
- 他社と迷っている
状況を聞いたうえで、ほかのスクールのほうが合うと思えば、そう伝えます。
無料体験授業と個別カウンセリングの中身と申し込み方を読むゆめさくエンジニア研究所は、プログラミングスクール「ゆめさくエンジニア」の運営側が書いているメディアです。









