🎉

Web Speed Hackathon 2024 参加記

2024/03/28に公開

今年も参加しました!
https://cyberagent.connpass.com/event/300386/

最終スコアは18位でしたが、上位勢がレギュレーションチェックを受けて順位が上がりました。

前回の結果(14位、183.60点)と比べるとかなり手ごたえを感じています。
スタッフ曰く「過去最高難度」にふさわしく、とても難しかったけれど、前回よりも「分かってやってる感」を感じてとても楽しかった。

以下、準備したこととやったことを記録しておきます。

心構え

  • 推測するな、計測せよ
  • 落ち着いて1つ1つ対応していこう
  • スコアに大きく影響しない改善はやらない
  • 短絡的な対応をしない、今回はじっくり知識を蓄える
  • コミット1つずつ

忘れがちなこと

  • Chrome拡張の影響を受けるためシークレットタブで確認する
  • 低速ネットワークで動かす
    • Developer Toolのスロットリング:高速3Gを選択

準備したこと

わかったこと

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プラグインで正規表現が静的解析できてよい
https://github.com/ota-meshi/eslint-plugin-regexp
eslint-plugin-regexpを入れる(正規表現チェック)

世界は我々の想像する以上に変化するが、ここまで繰り返さなくてよいやつ
世界は我々の想像する以上に変化する

覚えていない、たぶんChatで聞いたやつ
作品追加の画像プレビューを修正

ただのリンクをReact Routerを使うようにして、ページ全体のリロードをなくした
Linkをreact-router-domに変える
(コンテスト後)

このあとやりたいこと

この辺わからないので、要復習!

  • Suspense
  • useQuery
  • SSR
  • E2E、VRT

最後に

当日の午後はBリーグの試合を見に行くという重要な用事があったので、午前中はデプロイだけして夜から本格参戦でした。おかげで年甲斐もなく朝方までやってしまった。。。(疲)
2日間フル参加でなくても、ベストエフォートでもいいから参加することが大事。
誰でもなにか1つは学びになります。

次回はレギュレーションチェック受けられるスコアを取りたい!(と、(元)後輩のKさんと誓い合う)

Discussion