Performance: 4.7MB JS bundle with no code splitting causes 7-10s load times
Summary
cloud.vibekanban.com ships a 4.7MB uncompressed / 1.38MB gzip single JavaScript bundle with zero code splitting. This causes 7–10 second load times for users with moderate latency (e.g., mainland China → Cloudflare HKG edge).
Environment
- URL:
https://cloud.vibekanban.com - Server version:
x-server-version: 0.1.22 - Stack: React 18.3.1 SPA, Vite, Cloudflare CDN (HKG edge)
- User location: Beijing, China (200Mbps broadband)
- CF Edge: HKG (104.26.14.40, 172.67.68.156, 104.26.15.40)
Problem
1. Massive monolithic JS bundle (Critical)
The entire app ships as a single JS chunk (~4.7MB raw / ~1.38MB gzip). Inspecting the bundle contents reveals 100+ language syntax highlighting packs (Angular, Python, Java, Ruby, Lua, Fortran, COBOL, etc.) are all bundled into the main entry point.
For a kanban board view, none of these syntax packs are needed on first paint.
# Measured via curl from a CN server
JS bundle: 4.7MB uncompressed, 1.38MB gzip transfer
CSS bundle: 104KB uncompressed, 18KB gzip transfer
HTML shell: ~4KB2. SPA serial loading waterfall
Because the app is a pure client-side SPA (<div id="root">), the loading sequence is strictly serial:
HTML (TTFB ~1.05s) → JS download (~1.9s) → JS parse/exec → API data fetch → renderNo data can be fetched until the full 4.7MB bundle is downloaded, parsed, and executed. This serialization adds unnecessary seconds to every cold load.
3. HTML not cached at Cloudflare edge
cf-cache-status: DYNAMICEvery page navigation hits the origin server. Static assets correctly return cf-cache-status: HIT with max-age=14400, but the HTML shell could also be cached with appropriate cache rules since it's the same SPA shell for all routes.
Estimated Load Waterfall (Beijing user)
| Phase | Duration | Cumulative |
|---|---|---|
| DNS + TLS + TTFB | ~1.0s | 1.0s |
| JS download (1.38MB gzip) | ~1.9s | 2.9s |
| JS parse + execute (4.7MB) | ~1.5–2.5s | 4.4–5.4s |
| API data fetch | ~1.0–2.0s | 5.4–7.4s |
| Render | ~0.5–1.0s | 5.9–8.4s |
Real-world total: 7–10 seconds from navigation to usable content.
Suggested Fixes (by impact)
High Impact
Code split syntax highlighting packs — Dynamic
import()for language packs. Load only when a code block with that language is actually rendered. This alone could cut the JS bundle by 60–70%.Route-based code splitting — Split by route (kanban board, settings, editor, etc.) so each view only loads what it needs.
Lazy load heavy dependencies — Any large library not needed for initial render should be dynamically imported.
Medium Impact
Cache HTML at Cloudflare edge — Add a CF Cache Rule for the SPA shell HTML with short TTL (e.g., 60s) +
stale-while-revalidate. The HTML is identical for all routes.Preload/prefetch API data — Use
<link rel="preload">for critical API endpoints, or embed initial data in the HTML response.Enable Cloudflare Early Hints (103) — Push critical CSS/JS hints before the HTML response completes.
Lower Impact
Consider SSR/streaming — Server-side render the shell with critical data to eliminate the JS-parse-before-fetch waterfall.
Cloudflare Speed Brain — Enable speculative prefetch for returning users.
How to Reproduce
# Check bundle size
curl -s -o /dev/null -w '%{size_download} bytes (raw), %{time_total}s' \
-H 'Accept-Encoding: identity' \
'https://cloud.vibekanban.com/assets/index-*.js'
# Check gzip size
curl -s -o /dev/null -w '%{size_download} bytes (gzip), %{time_total}s' \
-H 'Accept-Encoding: gzip' \
'https://cloud.vibekanban.com/assets/index-*.js'
# Check cache status
curl -sI 'https://cloud.vibekanban.com/' | grep -i 'cf-cache-status'Impact
This primarily affects users with higher latency to the Cloudflare edge (Asia-Pacific, South America, Africa), but the 4.7MB bundle will cause slower-than-necessary loads for all users globally. VPN/proxy does not help since the bottleneck is app architecture, not network routing.
Source: BloopAI/vibe-kanban