web-speed-hackathon-2022に挑戦した

2023/01/06

最終更新:2023/04/12

web-speed-hackathon-2022に年末年始に挑戦してみた。

環境構築

ローカルが立ち上がるようにするまではREADMEの手順通りにやれば簡単だった。

しかし、計測環境まで準備するのは初めてだったのもあって2時間弱かかってしまった。やることとしては以下。

  1. web-speed-hackathon-2022-leaderboardをfork
  1. fork先のrepoのSettings>FeaturesのIssuesにチェックする(forkしたrepoはdefaultがOFFになっているため)
  1. fork先のrepoのSettings>Actions>GeneralのAllow all actions and reusable workflowsを選択してSaveする(forkしたrepoはactionsがdefault OFFになっている)
  1. 何らかのホスティングサービスにデプロイし、本番環境のURLを取得する(後述)
  1. Issuesにて、registration というラベルを作成しておく(これがないとactionsのif文に入らない)
  1. 後はドキュメント通りにissueを登録し、github actionsが動くか確認する

デプロイ

herokuのfree planが2022/11/29に終了していたため、どこにするか迷ったが色々調べた結果renderを選択した。

チューニング

初回スコアは19.2だった。今回は本番期間後に挑戦してるため時間の縛りなどもなかったことから特に着手事項に優先度は設けず、目についたことからどんどんやっていった。

画像の圧縮

初回アクセス時にとりあえずNetworkタブを見たところ、軒並み画像のダウンロードに時間がかかってたのでとりあえず圧縮に挑戦。

画像

https://saruwakakun.com/tools/png-jpeg-to-webp/にて、public/assets/images/races のものをwebpへの変換をした後デプロイ。スコアが上がったのを確認したので全てのassetsを圧縮するとスコアは19.2120.45と大幅に上がった。

コミット

バンドルサイズ

webpackのログを見ると約31Mあるのでこれを小さくしてみる。

画像

analyzer結果

画像

zengin-codeというものがデカすぎるが、初見でこれがなんなのかわからないためまずはlodashとmomentから取り組む。

lodash

使用箇所全て書き換えた結果31MB →29.23MBになった。スコアは120.45 → 131.25になった

コミット

 

画像

moment

使用箇所全てをJSのDateオブジェクトを使うように書き換えた結果 29.23MB →26.62MBになった。スコアはなぜか128.85に下がった。

コミット

画像

webpack

webpack.config.jsを見ていたところdevtool: "inline-source-map" とあり、distに吐き出されるコードが大きくなっていたのでこれを消したのと、mode: "development" となっていてwebpackの最適化を受けれなくなっていたのでproductionとしてビルドが走るようにすると大幅にサイズが小さくなった。スコアも大幅に上がり128.85→204.1に。

26.62MB → 4.29MB

コミット

画像

bebal周り

side-effect.js でimportしていたpolyfil周りが必要なさそうだったので一式消した。この時Uncaught ReferenceError: regeneratorRuntime is not definedと出てasync-awaitをbabelで読めなくなってしまったのでこちらの記事を参考にplugins: ["@babel/plugin-transform-runtime"]をwebpack.config.jsに追加した。

4.29MB → 3.26MB

204.1 → 224.55

コミット

画像

zengin-code

ついにこれ。調べたら銀行のデータらしい。公式?を見つけポチポチしていたところjsonを取ってこれそうだったのでNPM経由ではなくfetch経由でのデータ取得としてみた。ついにKBの世界にたどり着けた。

3.26MB → 419.07KB

224.55 → 382.3

コミット

画像

framer-motion

css animationとして、styled-componentsのkeyframesで定義したコンポーネントを使うように置き換える。

419.07KB → 290.07KB

382.3 → 389.55

コミット

画像

バンドル分割

Reactのlazyを使ってバンドルサイズの分割を試す。結果は以下。

290.07KB → 200.11KB

389.55 → 403.95

コミット

画像

Light house

スコアも400超えてなかなか速くなってきたのでLight houseを見てみる。結果は以下。

画像

あとはここに書かれていることを順番にやっていった。

コミット

Minify JavaScript

Reactの拡張機能を入れていると読み込まれるinstallHook.jsとreact-devtool-backend.jsが対象になっていたため一時的に拡張機能を削除した。

Reduce unused JavaScript

上記同様。

画像系

lazy loadingにする。アスペクト比をcanvasで計算していた箇所はcssに置き換えた。Top Viewの画像はlinkタグでpreloadした。なぜかサーバー側でasset urlにハッシュ値を付与していたのでこれをやめた。

Enable text compression

サーバーからのレスポンスを圧縮したら良いらしい。response headerにcontent-encoding が付与されればいいらしいのでサーバー側のコードを見た。調べるとfastify-compressというプラグインが公開されていたのでこれを使用した。fastifyがv3系だったのでv5.0.0以下じゃないと動かない。

fastifyを最新のv4に上げようとしたが、周辺ライブラリも上げないといけなかったのとlogger周りの破壊的変更があったためやめた。

結果

ここまでやったらPerfomanceは100になったのでスコア計測したところ464.2に上がった。

まとめ

本番期間であれば11位になるスコアまで上げることができた。

勘所は掴めたので、今年の開催では10位以内にランクインしたい。

参考にした記事

by me a coffee