Web Engine Docs
Preparing documentation
Use the search bar to quickly find any topic
Preparing documentation
Use the search bar to quickly find any topic
Production build optimization, asset bundling, and deployment strategies for Web Engine applications.
Web Engine uses modern build tools (Vite, Turbo) for fast development and optimized production builds. This guide covers build configuration, asset optimization, and deployment to various hosting platforms.
Monorepo orchestration with intelligent caching
Lightning-fast dev server and optimized builds
Automatic chunking for optimal loading
The monorepo structure uses Turborepo for build orchestration and Vite for application bundling:
{"pipeline": {"build": {"dependsOn": ["^build"],"outputs": [".next/**", "dist/**"]},"dev": {"cache": false,"persistent": true},"lint": {"outputs": []}}}
# Build all packages and appsnpm run build# Build specific appnpm run build --filter=@web-engine-dev/studionpm run build --filter=@web-engine-dev/playernpm run build --filter=@web-engine-dev/docs# Build with specific packagesnpm run build:packages# Clean build cachenpm run clean
import { defineConfig } from "vite";import react from "@vitejs/plugin-react";import { getChunkName } from "@web-engine-dev/build-config";export default defineConfig({plugins: [react()],build: {target: "es2020",minify: "terser",sourcemap: true,rollupOptions: {output: {// Chunking strategy for optimal cachingmanualChunks: (id) => {return getChunkName(id);},// Asset namingassetFileNames: "assets/[name]-[hash][extname]",chunkFileNames: "chunks/[name]-[hash].js",entryFileNames: "entries/[name]-[hash].js",},},terserOptions: {compress: {drop_console: true, // Remove console.logdrop_debugger: true, // Remove debugger statementspure_funcs: ["console.debug", "console.trace"],},},},// Asset optimizationassetsInlineLimit: 4096, // Inline assets < 4KB// Dependencies to optimizeoptimizeDeps: {include: ["three","bitecs","@dimforge/rapier3d-compat",],},});
Web Engine uses a strategic chunking system defined in @web-engine-dev/build-config:
export const chunkingStrategy = {vendor: ["react","react-dom","three","@react-three/fiber","@react-three/drei","zustand",],physics: ["@dimforge/rapier3d-compat","@react-three/rapier",],ui: ["@radix-ui/react-slot","@radix-ui/react-dialog",// ... all Radix UI components],};export function getChunkName(id: string): string | null {if (id.includes("node_modules")) {if (chunkingStrategy.vendor.some(v => id.includes(v)))return "vendor";if (chunkingStrategy.physics.some(v => id.includes(v)))return "physics";if (chunkingStrategy.ui.some(v => id.includes(v)))return "ui-libs";return "deps";}return null;}
Chunk Benefits
Strategic chunking enables:
import { KTX2Loader } from "three/examples/jsm/loaders/KTX2Loader";import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";// Configure KTX2 loader for compressed texturesconst ktx2Loader = new KTX2Loader();ktx2Loader.setTranscoderPath("/basis/");ktx2Loader.detectSupport(renderer);// Configure DRACO loader for mesh compressionconst dracoLoader = new DRACOLoader();dracoLoader.setDecoderPath("/draco/");// Use in GLTF loadergltfLoader.setKTX2Loader(ktx2Loader);gltfLoader.setDRACOLoader(dracoLoader);
# Optimize GLTF with gltfpackgltfpack -i model.gltf -o model.glb -cc# Options:# -cc: Compress meshes with Draco# -tc: Compress textures with KTX2/Basis# -si 0.5: Simplify meshes to 50% triangles
# API ConfigurationVITE_API_URL=https://api.myengine.comVITE_PLAYER_URL=https://play.myengine.comVITE_DOCS_URL=https://docs.myengine.com# Feature FlagsVITE_ENABLE_ANALYTICS=trueVITE_ENABLE_MULTIPLAYER=trueVITE_ENABLE_ASSET_STREAMING=true# CDN ConfigurationVITE_CDN_URL=https://cdn.myengine.comVITE_ASSET_BASE_URL=https://assets.myengine.com# BrandingVITE_ENGINE_NAME=MyEngineVITE_ENGINE_VERSION=1.0.0
// Access env variablesconst config = {apiUrl: import.meta.env.VITE_API_URL,playerUrl: import.meta.env.VITE_PLAYER_URL,enableAnalytics: import.meta.env.VITE_ENABLE_ANALYTICS === "true",};
{"buildCommand": "turbo run build --filter=@web-engine-dev/studio","outputDirectory": "apps/studio/.next","framework": "nextjs","rewrites": [{"source": "/api/:path*","destination": "https://api.myengine.com/:path*"}],"headers": [{"source": "/assets/(.*)","headers": [{"key": "Cache-Control","value": "public, max-age=31536000, immutable"}]}]}
# Deploy to Vercelvercel --prod# Deploy specific appvercel --prod --cwd apps/studio# Environment variablesvercel env add VITE_API_URL production
[build]command = "turbo run build --filter=@web-engine-dev/player"publish = "apps/player/dist"[[redirects]]from = "/api/*"to = "https://api.myengine.com/:splat"status = 200[[headers]]for = "/assets/*"[headers.values]Cache-Control = "public, max-age=31536000, immutable"[[headers]]for = "/*.js"[headers.values]Cache-Control = "public, max-age=31536000, immutable"
# Build commandturbo run build --filter=@web-engine-dev/docs# Output directoryapps/docs/out# Environment variablesNODE_VERSION=18
For optimal performance, serve static assets from a CDN:
// Configure asset base URLconst ASSET_CDN = import.meta.env.VITE_CDN_URL || "";export function getAssetUrl(path: string): string {return `${ASSET_CDN}${path}`;}// Usageconst modelUrl = getAssetUrl("/models/character.glb");const textureUrl = getAssetUrl("/textures/grass.ktx2");
CDN Best Practices
Pre-Deployment Checklist
// Track performance metricsimport { PerformanceMonitor } from "@web-engine-dev/logging";const perfMonitor = new PerformanceMonitor(logger);// Send metrics to analyticsfunction reportMetrics() {const snapshot = perfMonitor.getSnapshot();analytics.track("performance", {fps: snapshot.fps.avg,frameTime: snapshot.frameTime.avg,heapUsed: snapshot.memory?.heapUsed,});}// Report every 30 secondssetInterval(reportMetrics, 30000);
Monitor key metrics in production:
Sentry, LogRocket, or similar for error monitoring
Track user behavior and performance metrics
Core Web Vitals, FPS, load times
Monitor API and CDN availability
FROM node:18-alpine AS builderWORKDIR /app# Install dependenciesCOPY package*.json ./COPY turbo.json ./RUN npm ci# Copy sourceCOPY . .# BuildRUN npm run build --filter=@web-engine-dev/studio# Production imageFROM node:18-alpineWORKDIR /appCOPY --from=builder /app/apps/studio/.next ./.nextCOPY --from=builder /app/node_modules ./node_modulesCOPY --from=builder /app/package.json ./package.jsonEXPOSE 3000CMD ["npm", "start"]
version: "3.8"services:studio:build:context: .dockerfile: apps/studio/Dockerfileports:- "3000:3000"environment:- NODE_ENV=production- VITE_API_URL=https://api.myengine.complayer:build:context: .dockerfile: apps/player/Dockerfileports:- "5173:80"server:build:context: .dockerfile: apps/server/Dockerfileports:- "4000:4000"environment:- NODE_ENV=production