Web Speed Hackathon 2024 参加記
今年も参加しました!
最終スコアは18位でしたが、上位勢がレギュレーションチェックを受けて順位が上がりました。
前回の結果(14位、183.60点)と比べるとかなり手ごたえを感じています。
スタッフ曰く「過去最高難度」にふさわしく、とても難しかったけれど、前回よりも「分かってやってる感」を感じてとても楽しかった。
以下、準備したこととやったことを記録しておきます。
心構え
- 推測するな、計測せよ
- 落ち着いて1つ1つ対応していこう
- スコアに大きく影響しない改善はやらない
- 短絡的な対応をしない、今回はじっくり知識を蓄える
- コミット1つずつ
忘れがちなこと
- Chrome拡張の影響を受けるためシークレットタブで確認する
- 低速ネットワークで動かす
- Developer Toolのスロットリング:高速3Gを選択
準備したこと
-
これ読んで基本を思い出す
https://roadmap.sh/best-practices/frontend-performance -
Viteドキュメント読む
https://ja.vitejs.dev/guide/performance.html
Viteだと思ったんだけどなあ。でもesbuildのことも知れた -
去年のcut0さんリポジトリ確認
https://github.com/cut0/web-speed-hackathon-2023 -
今回アナウンスされた環境の準備
- Node LTS(20.11.1) をnvmでインストール
-
2020出題のねらいと解説
https://github.com/CyberAgentHack/web-speed-hackathon-2020/wiki/Web-Speed-Hackathon-Online-出題のねらいと解説 -
Cursorを準備
https://cursor.sh/
会社のデキる後輩から教えてもらった
VSCodeベースでとても良い
OpenAIのAPIキーを使ってGPT4-Turboを使った
わかったこと
tsupのbundle解析どうやる?
tsupはesbuildを使っているとのこと。
Viteのドキュメントを見ていたおかげでesbuildの存在を知っていたのですんなりと理解できた。
Analyzerどうやっていれるのか分からなかったが、だいぶ時間が経ってからわかった。
metafile: trueになっていると
workspaces/client/dist/metafile-iife.json
がビルド時に生成されるので、これを
https://esbuild.github.io/analyze/
で読み込ませると、バンドルが表示される。
tsupでCode Splittingできない
tsupではiife, esmなどの形式が指定できる。
今回使われている設定はiifeで、この設定だとsplittingされない。
esmだとsplittingできるらしいが、node_modulesのライブラリが含まれないので使えなかった。
今回のアプリはWindowsだと画像のデコードができなかった
難読化のための暗号化処理が機能としてあったが、Windowsで動かしているときには一向にマンガが表示されなかった。
デプロイしたものでは表示されていたので、WSLに引っ越したら問題なく表示された。
ディレクトリを扱うものはLinuxとWindowsで相性あるので、はじめからUbuntuでやればよかった。
Reactちょっとわかった
前回Reactワカランかったけど、今回はuseEffect, useStateについて勉強していったおかげで、コンポーネント周りの修正が自力でできた。
AIに聞いた答えをそのまま鵜呑みにせず、仕組みを理解して自分で修正できるのってとても大事。
githubのコミット一覧
モジュール削減
[TTI] tsupの設定見直し
tsup.configを修正:minify,target,treeshake
NODE_ENV production
[TTI] noExternalやっぱりいらなかった、sourcemapをfalseに
tsup修正
[FCP] Dateを使った
moment削除
[FCP] Mapとfloor,clamp->Math
GPTで説明してもらった
lodashやめる
[FCP] 最新のChromeに対応すればよいルールなのでpolyfillは削除
polyfill削除
[FCP] 令和の時代にjQueryがあったので消す
jQuery消す
(コンテスト後)
[FCP] Footerに含まれていた利用規約の文学をAPI化して外出し
テキストにしてもよかった。前回はGraphQLでサッパリわからなかったが、今回はAPIの追加がわかりやすくてよかった。
利用規約をAPI化
画像まわり圧縮
[FCP] footerのsvgファイルサイズを圧縮
svgサイズ削減
[FCP,LCP,CLS] トップのカバー画像がコンポーネントとして含まれていたのをwebp化
ついでに上にかぶせて表示していたロゴもあわせてwebp化し、16:9で表示(aspect-ratio)
preloadしたがこれはあとで消した(トップなので)
hero.webpに変更
[FCP] Imageを遅延ロードすることでスクロール前の画像を取得しないようにした
Imageをloading=lazy
[FCP?] footerロゴをpreloadしているが初期画面表示の枠外なので削除(loading=lazy)
前後で測定できておらず効果不明、もしかしたらpreloadしたままがよいのか?
ロゴのpreloadやめる
[FCP] canvasを使わない
Separatorもcanvasだった
canvasを使わない(useImage->getImageUrl, Separator)
(コンテスト後)
[FCP,CLS] カバー画像のサイズでかすぎたので1600/900にリサイズ
hero.webpを縮小
(コンテスト後)
フォント
[FCP] ソースコードgrepしてfont使用しているところはなかったので削除
使ってないフォントを削除
通信
[LCP?] Hono/compressでサーバーからのHTTPレスポンスをgzip圧縮
br圧縮は対応していなかった
HTTP gzip圧縮
コンポーネント最適化
[FCP] SvgIconを全部インポートしていた。使っているもののみインポート
material-iconの全部インポートをやめる
[FCP] トップページのコンポーネントを遅延ロードしたが、そもそもjsがchunkされていないので意味ない(戻してない)
useEffectでデータ取得できたら描画するようにしたが、Suspenseで囲まれているので意味はなかった(戻してない)
トップページ useEffect
Topで取得したピックアップ(feature)、ランキング(ranking)、本日の更新(release)のデータには、それぞれのCardで表示する情報が含まれているにもかかわらず、Cardのコンポーネントで取得しなおしていた。
TopからCardコンポーネントにデータをproprety渡ししてネットワーク節約
Topページのbook fetchを削除
↑の修正でコンポーネントのリンクを消してしまったので復活
Topページ リンク切れ修正
useEffectのバグを修正
トップ画面のfeature,ranking,todayがたまに表示されなくなるバグ修正
(コンテスト後)
[CLS] トップページのカバー画像を先に表示させる
カバー画像の下はある程度高さを取ってフッターが見えないようにしてガタン対策
作者詳細とエピソード一覧のレイアウトシフト対応
↑の修正でトップページのFooterがはみ出てしまったのを修正
Footerの横幅修正
(コンテスト後)
急に検索画面の採点ができなくなってしまったので暫定対応
因果は不明だがこのあとの採点は成功していた
検索画面のSuspense元に戻す
その他
wasmは怪しいと思ってChatで聞いて直したやつ
初期化が何度もされているので、一度だけにした
効果は不明
wasm初期化処理
前回もあったReDoS対策
ログイン画面の正規表現を修正
メールアドレスとパスワードの正規表現を修正
今回使わなかったが、このEslintプラグインで正規表現が静的解析できてよいeslint-plugin-regexpを入れる(正規表現チェック)
世界は我々の想像する以上に変化するが、ここまで繰り返さなくてよいやつ
世界は我々の想像する以上に変化する
覚えていない、たぶんChatで聞いたやつ
作品追加の画像プレビューを修正
ただのリンクをReact Routerを使うようにして、ページ全体のリロードをなくした
Linkをreact-router-domに変える
(コンテスト後)
このあとやりたいこと
この辺わからないので、要復習!
- Suspense
- useQuery
- SSR
- E2E、VRT
最後に
当日の午後はBリーグの試合を見に行くという重要な用事があったので、午前中はデプロイだけして夜から本格参戦でした。おかげで年甲斐もなく朝方までやってしまった。。。(疲)
2日間フル参加でなくても、ベストエフォートでもいいから参加することが大事。
誰でもなにか1つは学びになります。
次回はレギュレーションチェック受けられるスコアを取りたい!(と、(元)後輩のKさんと誓い合う)
Discussion