12 KiB
Cosmo Frontend Asset Loading Strategy Analysis
Executive Summary
The Cosmo frontend project implements a 3D solar system visualization using Three.js and React-Three-Fiber. The asset loading strategy currently uses a mix of on-demand fetching and preloading patterns, with assets served through a backend API proxy.
1. Asset Inventory
1.1 Texture Assets (Primary Location: Backend Upload)
Backend Location: /Users/jiliu/WorkSpace/cosmo/backend/upload/texture/
- Total Size: ~19 MB
- Format: Primarily JPEG with some PNG
- Built/Dist Location:
/Users/jiliu/WorkSpace/cosmo/frontend/dist/textures/
Key Texture Files (by size):
| File | Size | Purpose |
|---|---|---|
| 2k_moon.jpg | 1.0 MB | Moon surface texture |
| 2k_venus_surface.jpg | 868 KB | Venus surface |
| 2k_mercury.jpg | 856 KB | Mercury surface |
| 2k_sun.jpg | 804 KB | Sun/Star texture |
| 2k_mars.jpg | 736 KB | Mars surface |
| 2k_jupiter.jpg | 488 KB | Jupiter surface |
| 2k_earth_daymap.jpg | 456 KB | Earth day side |
| 2k_earth_nightmap.jpg | 256 KB | Earth night side |
| 2k_stars_milky_way.jpg | 248 KB | Milky Way background |
| 2k_neptune.jpg | 236 KB | Neptune surface |
| 2k_venus_atmosphere.jpg | 228 KB | Venus atmosphere |
| 2k_saturn.jpg | 196 KB | Saturn surface |
| 2k_uranus.jpg | 76 KB | Uranus surface |
| 2k_saturn_ring_alpha.png | 12 KB | Saturn ring transparency |
Additional Textures (comets, dwarf planets, moons):
- 2k_pluto.jpg: 3.8 MB (largest single file)
- Various comet/asteroid textures: 300-500 KB each
- Moon textures (Ganymede, Io, Titan, Mimas): 350-360 KB each
1.2 3D Model Assets (GLB/GLTF Format)
Backend Location: /Users/jiliu/WorkSpace/cosmo/backend/upload/model/
- Total Size: ~24 MB
- Format: GLB (binary GLTF)
Key Model Files (by size):
| File | Size | Purpose |
|---|---|---|
| juno.glb | 8.6 MB | Juno space probe |
| cassini.glb | 1.6 MB | Cassini spacecraft |
| voyager_2.glb | 1.6 MB | Voyager 2 probe |
| parker_solar_probe.glb | 436 KB | Parker Solar Probe |
| voyager_1.glb | 280 KB | Voyager 1 probe |
| webb_space_telescope.glb | ~1-2 MB (from list) | JWST |
| new_horizons.glb | ~1-2 MB (from list) | New Horizons probe |
| perseverance.glb | ~1-2 MB (from list) | Mars Perseverance rover |
Observations:
- Juno.glb (8.6 MB) is significantly larger than other models
- Most probes range 280 KB to 1.6 MB
- Total probe models: ~24 MB for ~8 spacecraft
2. Asset Loading Strategy
2.1 Texture Loading (Detailed Implementation)
File: /Users/jiliu/WorkSpace/cosmo/frontend/src/components/CelestialBody.tsx
// Current Loading Pattern:
1. Component mounts (Planet component)
2. fetchBodyResources(body.id, 'texture') - calls API
3. Finds main texture (excludes 'atmosphere' and 'night')
4. Constructs URL: /upload/{file_path}
5. useTexture(texturePath) - Three.js texture loader
6. Renders mesh with loaded texture
// Key Line:
const texture = texturePath ? useTexture(texturePath) : null;
Loading Characteristics:
- Type: On-demand (per celestial body)
- Caching: useTexture hook likely caches within session
- Error Handling: Falls back to null (gray placeholder material)
- Performance: No preloading - each body texture loads when component mounts
2.2 Model Loading (3D Probes)
File: /Users/jiliu/WorkSpace/cosmo/frontend/src/components/Probe.tsx
// Current Loading Pattern:
1. Component mounts (Probe component)
2. fetchBodyResources(body.id, 'model') - calls API
3. Gets first model resource + scale metadata
4. Constructs URL: /upload/{file_path}
5. useGLTF.preload(fullPath) - PRELOADING ENABLED
6. setModelPath(fullPath)
7. useGLTF(modelPath) - loads and parses GLB
// Key Implementation:
useGLTF.preload(fullPath); // Preload before rendering
const gltf = useGLTF(modelPath); // Actual load
Loading Characteristics:
- Type: On-demand with optional preloading
- Preloading: Yes -
useGLTF.preload()is called (Line 281) - Caching: useGLTF hook caches in session
- Scale Handling: Custom scale from
extra_data.scale - Fallback: ProbeFallback component renders red sphere if load fails
- Performance: Preload triggered immediately, improves perceived load time
2.3 Background/Static Assets
File: /Users/jiliu/WorkSpace/cosmo/frontend/src/components/Scene.tsx
// Procedural Assets (NO external files):
1. BackgroundStars (radius=300, count=5000, procedural)
2. AsteroidBelts (procedurally generated)
3. Nebulae (procedurally generated)
4. Constellations (data-driven but rendered procedurally)
// Data-Driven Assets (fetched from API):
1. Stars (real star catalog data)
2. Galaxies (CanvasTexture generated)
3. Satellites/Planets (textures fetched on demand)
Observations:
- Extensive use of procedural generation reduces asset file count
- Galaxy textures created with CanvasTexture (no disk files)
- Star data loaded from API, rendered with simple geometry
3. Loading Flow & Architecture
3.1 Request Path
Frontend Component
↓
fetchBodyResources(bodyId, type)
↓
API Call: /api/celestial/resources/{bodyId}?resource_type=texture|model
↓
Backend API (Port 8000)
↓
Vite Proxy Dev: localhost:8000/upload/{type}/{filename}
OR
Nginx Production: proxy to backend
↓
Actual File: /backend/upload/{type}/{filename}
↓
Response to Frontend
↓
useTexture() or useGLTF()
↓
Three.js Renderer
3.2 API Integration Points
File: /Users/jiliu/WorkSpace/cosmo/frontend/src/utils/api.ts
// Fetch function signature:
export async function fetchBodyResources(
bodyId: string,
resourceType?: string
): Promise<{
body_id: string;
resources: Array<{
id: number;
resource_type: string;
file_path: string; // e.g., "texture/2k_sun.jpg"
file_size: number;
mime_type: string;
created_at: string;
extra_data?: Record<string, any>; // scale, etc.
}>;
}>
4. Vite Build Configuration
File: /Users/jiliu/WorkSpace/cosmo/frontend/vite.config.ts
export default defineConfig({
plugins: [react()],
server: {
host: '0.0.0.0',
port: 5173,
proxy: {
'/api': {
target: 'http://localhost:8000',
changeOrigin: true,
},
'/upload': {
target: 'http://localhost:8000',
changeOrigin: true,
},
'/public': {
target: 'http://localhost:8000',
changeOrigin: true,
},
},
},
})
Current Configuration Analysis:
- No explicit asset optimization: No image compression, no WebP conversion
- No size limits: All assets proxied without size constraints
- No chunking strategy: Vite default chunks (1.2 MB JS bundle observed)
- Proxy strategy: All assets proxied through backend (good for dynamic content)
5. Build Output Analysis
Dist Directory: /Users/jiliu/WorkSpace/cosmo/frontend/dist/
- Total Size: ~20 MB
- JavaScript Bundle: 1.2 MB (index-c2PfKiPB.js)
- CSS: 9.8 KB
- Textures: ~7.9 MB (in dist, smaller than backend copy)
- Models: ~12.8 MB (in dist)
Key Finding: Textures in dist folder are smaller than backend source, suggesting some optimization (JPEG compression) during build/deploy.
6. Lazy Loading & Code Splitting
File: /Users/jiliu/WorkSpace/cosmo/frontend/src/App.tsx
// Already Implemented:
const InterstellarTicker = lazy(() =>
import('./components/InterstellarTicker')
.then(m => ({ default: m.InterstellarTicker }))
);
const MessageBoard = lazy(() =>
import('./components/MessageBoard')
.then(m => ({ default: m.MessageBoard }))
);
const BodyDetailOverlay = lazy(() =>
import('./components/BodyDetailOverlay')
.then(m => ({ default: m.BodyDetailOverlay }))
);
// Wrapped in Suspense:
<Suspense fallback={null}>
<InterstellarTicker />
</Suspense>
Status:
- Lazy loading implemented for 3 non-critical components
- Suspense fallback set to null (no skeleton loading)
- No lazy loading for 3D rendering components (CelestialBody, Probe, Scene)
7. Current Optimization Opportunities
7.1 Identified Issues
-
No Texture Compression
- Total texture size: 19 MB (backend) → 7.9 MB (dist)
- JPEG quality likely could be reduced further
- No WebP fallback for modern browsers
- No LOD (Level of Detail) system
-
Large Model File
- Juno.glb: 8.6 MB (30% of all model assets)
- No model optimization/decimation
- No LOD for probes
- All vertices/triangles loaded even when zoomed out
-
No Batch Asset Loading
- Each body texture loaded individually
- 10+ API calls for visible celestial bodies
- No batching or parallel loading optimization
- No request deduplication
-
All-or-Nothing Texture Loading
- Texture loading blocks render until complete
- Falls back to gray if load fails
- No progressive/streaming load
-
Limited Caching Strategy
- useTexture/useGLTF cache only within session
- No persistent browser cache headers optimization
- No service worker caching
-
Background Star Data
- Stars component loads 1000+ star systems per API call
- No pagination or frustum culling
- All stars rendered regardless of visibility
7.2 Existing Optimizations
POSITIVE:
✓ Procedural generation for backgrounds (saves ~10 MB+ in textures)
✓ useGLTF.preload() for probe models
✓ useTexture hook caching
✓ Lazy loading for non-critical UI components
✓ Reused geometry for identical objects (stars use single SphereGeometry)
✓ Billboard optimization for labels (distance culling)
✓ Selective texture filtering (excludes atmosphere/night variants)
8. Performance Summary
Asset Totals:
- Textures: 19 MB (backend) / 7.9 MB (dist)
- Models: 24 MB (backend) / 12.8 MB (dist)
- JavaScript: 1.2 MB
- Total Transfer: ~32 MB initial + on-demand loading
Loading Pattern:
- Initial Load: 1.2 MB (JS) + procedural background rendering
- Per-Scene: ~100-500 KB (depending on visible bodies)
- Per-Probe: 280 KB - 8.6 MB (first load)
Current Bottlenecks:
- Juno probe (8.6 MB) loading time
- Sequential texture API calls
- No partial/progressive loading
- Large JPEG files (Moon: 1 MB, Venus: 868 KB)
9. File Locations Summary
Source Code:
- Main 3D Scene:
/Users/jiliu/WorkSpace/cosmo/frontend/src/components/Scene.tsx - Texture Loading:
/Users/jiliu/WorkSpace/cosmo/frontend/src/components/CelestialBody.tsx(Line 102-123) - Model Loading:
/Users/jiliu/WorkSpace/cosmo/frontend/src/components/Probe.tsx(Line 261-295) - API Integration:
/Users/jiliu/WorkSpace/cosmo/frontend/src/utils/api.ts - Build Config:
/Users/jiliu/WorkSpace/cosmo/frontend/vite.config.ts
Asset Locations:
- Texture Source:
/Users/jiliu/WorkSpace/cosmo/backend/upload/texture/ - Model Source:
/Users/jiliu/WorkSpace/cosmo/backend/upload/model/ - Texture Build Output:
/Users/jiliu/WorkSpace/cosmo/frontend/dist/textures/ - Model Build Output:
/Users/jiliu/WorkSpace/cosmo/frontend/dist/models/ - Documentation:
/Users/jiliu/WorkSpace/cosmo/frontend/PERFORMANCE_OPTIMIZATION.md
10. Recommendations (Priority Order)
Quick Wins (1-2 hours):
- Implement image compression (JPEG quality: 80-85%)
- Add WebP format with JPEG fallback
- Set proper Cache-Control headers on backend
- Implement batch/parallel texture loading
Medium Term (4-8 hours):
- Add texture LOD (Load specific resolution by distance)
- Implement model decimation for Juno probe
- Add progressive texture loading (low-res → high-res)
- Implement frustum culling for star systems
Long Term (16+ hours):
- Implement texture atlas for small textures
- Add KTX2/Basis texture compression
- Implement virtual scrolling for star catalog
- Add service worker for persistent caching