Perf: cut first-load JS ~8× via route splitting + deferred web3 (PlayBlind teardown)

オープン
#779 コメント 2 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
5/5
見積もり時間
1週間以上
初心者へのやさしさ
35/100
issue の種類
リファクタリング
明瞭さ
おおむね明確
活発さ
活発
技術スタック
chart.js, react, typescript, vite

調査の方向性

Start by reading vite.config.ts and tracing the app’s route components and wallet initialization; the issue names no route files or tests. Compare the initial bundle with route and wallet code to identify what loads at startup. Done means route splitting and deferred web3 loading reduce first-load JavaScript without changing dependency versions.

索引モデルが issue の本文から書いたものです。

説明

enhancement

Summary

Competitive teardown of playblind.com (a similar onchain poker site with notably faster UX) shows they run nearly the identical stack we do — Vite + React + wagmi/viem + Reown AppKit + MetaMask/Coinbase. They are not fast because of an exotic framework. They are fast because of how they split and defer-load the same libraries. Our entire perceived-speed gap is bundling strategy.

The core finding: ~8× larger first-load

PlayBlind Us
Build tool Vite Vite
Framework React React 19
Web3 wagmi + viem + WalletConnect/Reown + MetaMask/Coinbase same
Initial JS ~218 KB (index.js) ~1.8 MB gzip / 7.4 MB raw, 22 chunks
Route splitting ~40 route-level chunks (Lobby, Table, Admin, Blog, Replay, ProvablyFair…) 0 routes split
Web3 stack lazy-loaded post-paint in an 800 KB Boot chunk loaded up front
React.lazy usage extensive 1 in the whole app

What's loaded up front for us, before first paint:

  • index-BY5dEnPJ.js — 626 KB gzip of pure wallet code (walletconnect / wagmi / coinbase / metamask / ethers / appkit)
  • index.esm-zM1Edlf2.js — 693 KB gzip of cosmjs + bip39 (gameplay signing)
  • crypto-browserify-B2Ep7zwg.js — 145 KB gzip

vite.config.ts also sets manualChunks: undefined, disabling Vite's splitting heuristics.

Proposed optimisations (impact-ordered)

  • Route-level code splitting (biggest win). 524 source files, 0 routes split. Wrap route components in React.lazy + Suspense. Lobby shouldn't ship the table/game engine; table shouldn't ship admin/profile.
  • Defer the web3 stack. Initialize Reown/wagmi lazily — only on "Connect Wallet" / deposit / withdraw — not at app boot. This is the single biggest lever (626 KB gz off first load).
  • Split the cosmjs/bip39 chunk (693 KB gz). Only needed once a wallet exists / a game is joined, not on the lobby/marketing view.
  • Re-enable manualChunks in vite.config.ts (remove manualChunks: undefined); let Rollup split vendors or define explicit groups (react / web3 / cosmos / charts).
  • Lazy-load chart.js + framer-motion — only on stats/profile screens, not the table.
  • Transport/caching parity: serve /assets/* with cache-control: immutable, max-age=31536000 (filenames are hashed), enable Brotli (~15-20% over gzip), HTTP/2/3, preconnect font/RPC origins. PlayBlind serves via Caddy with immutable 1-yr caching.
  • Optimise SVGs — b52CardBack.svg 101 KB, PokerProfile.svg 89 KB; run SVGO (likely -50-70%).

Recommendation

Do route splitting + deferred wallet init first — ~80% of the perceived-speed gap lives there, and both are low-risk config/wrapper changes, not rewrites.

Caveat: Node is pinned ≤22.13 for the Cosmos SDK, so these changes should stay bundling-config only and not touch dependency versions.


Findings from a bundle teardown on 2026-10-13 comparing our built build/assets against playblind.com's live assets.

主要言語
TypeScript
スター
2
フォーク
5
平均マージ
22時間 35分
マージ済み PR(30日)
91

環境構築

このプロジェクトの環境構築ファイルはまだ確認していません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

block52/ui のほかの issue

block52/ui の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。