mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 12:10:46 +00:00
94f2293149
## Summary Cuts the main JS chunk from **2,891 KB (732 KB gzip)** to **1,679 KB (412 KB gzip)** by fixing two bundling issues and removing/replacing heavy dependencies. Measured with a per-module `renderedLength` analysis of the rolldown output (its prod sourcemaps are malformed, so sourcemap-based tools misattribute sizes). | Chunk | Before | After | |---|---|---| | `index-*.js` (min) | 2,891 KB | 1,679 KB | | `index-*.js` (gzip) | 732 KB | **412 KB** | ## Changes - **Sim worker moved out of the main bundle (~512 KB).** The `?worker&inline` payload is now reached through a dynamic `import()`, so it lands in its own lazy chunk fetched when a game starts. The worker itself still uses Vite's inline Blob mechanism (with its `data:` URL fallback) — runtime instantiation is byte-for-byte unchanged. - **Replaced `lit-markdown` with `marked` + the already-bundled DOMPurify (~380 KB).** lit-markdown transitively pulled sanitize-html, htmlparser2, postcss, and two copies of entities into the client just to render news markdown. New `src/client/Markdown.ts` matches its image-stripping default. - **Dropped `colorjs.io` (~114 KB).** It was only used for ΔE2000 distance in `ColorAllocator`; colord's lab plugin (already imported there) provides the same CIEDE2000 via `.delta()`. Only relative magnitudes are compared, so allocation behavior is unchanged. - **`msdf-atlas.json` (~319 KB) fetched at runtime** like the atlas PNG, preloaded in parallel with worker init in `ClientGameRunner` so game-load latency is unaffected. - **Tailwind CSS no longer shipped twice (~158 KB).** `o-modal` imported `styles.css?inline`, duplicating the emitted stylesheet as a JS string. It now adopts a constructed stylesheet built from the document's own CSS (HTTP-cache hit in prod, `<style>` tags + HMR re-sync in dev) via `SharedStyles.ts`. - **Debug GUI lazy-loaded.** lil-gui + `gl/debug/*` now load on first toggle (46 KB lazy chunk) instead of shipping in the main bundle. Also looked at the `import * as d3` in RadialMenu (~84 KB) but left it: rolldown tree-shakes the metapackage well and all but ~2 KB is the genuine dependency closure of the selection/transition/shape/color APIs in use. ## Test plan - [x] `tsc --noEmit` clean - [x] ESLint clean - [x] Full test suite passes (1,374 + 65 tests) - [x] `npm run build-prod` succeeds; worker/debug chunks present in `asset-manifest.json` for the R2 upload - [ ] Manual smoke test in dev: start a game (worker dev path), open a modal (shared stylesheet), open news modal (markdown rendering) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
125 lines
4.4 KiB
JSON
125 lines
4.4 KiB
JSON
{
|
|
"name": "openfront-client",
|
|
"scripts": {
|
|
"build-dev": "concurrently \"tsc --noEmit\" \"vite build --mode development\"",
|
|
"build-prod": "concurrently --kill-others-on-fail \"tsc --noEmit\" \"vite build\"",
|
|
"start:client": "vite",
|
|
"start:server": "tsx src/server/Server.ts",
|
|
"start:server-dev": "cross-env GAME_ENV=dev NUM_WORKERS=2 TURNSTILE_SITE_KEY=1x00000000000000000000AA API_KEY=WARNING_DEV_API_KEY_DO_NOT_USE_IN_PRODUCTION DOMAIN=localhost GIT_COMMIT=DEV tsx src/server/Server.ts",
|
|
"dev": "cross-env GAME_ENV=dev concurrently \"npm run start:client\" \"npm run start:server-dev\"",
|
|
"dev:host": "cross-env GAME_ENV=dev VITE_HOST=lan concurrently \"npm run start:client\" \"npm run start:server-dev\"",
|
|
"dev:staging": "cross-env GAME_ENV=dev API_DOMAIN=api.openfront.dev concurrently \"npm run start:client\" \"npm run start:server-dev\"",
|
|
"dev:prod": "cross-env GAME_ENV=dev API_DOMAIN=api.openfront.io concurrently \"npm run start:client\" \"npm run start:server-dev\"",
|
|
"docs:map-generator": "cd map-generator && go doc -cmd -u -all",
|
|
"tunnel": "npm run build-prod && npm run start:server",
|
|
"test": "vitest run && vitest run tests/server",
|
|
"perf": "npx tsx tests/perf/run-all.ts",
|
|
"perf:game": "npx tsx tests/perf/fullgame/FullGamePerf.ts",
|
|
"test:coverage": "vitest run --coverage",
|
|
"format": "prettier --ignore-unknown --write .",
|
|
"format:map-generator": "cd map-generator && go fmt .",
|
|
"lint": "eslint",
|
|
"lint:fix": "eslint --fix",
|
|
"prepare": "husky",
|
|
"gen-maps": "cd map-generator && go run . && npm run format",
|
|
"inst": "npm ci --ignore-scripts"
|
|
},
|
|
"lint-staged": {
|
|
"**/*": [
|
|
"eslint --fix",
|
|
"prettier --ignore-unknown --write"
|
|
]
|
|
},
|
|
"devDependencies": {
|
|
"@datastructures-js/priority-queue": "^6.3.5",
|
|
"@eslint/compat": "^2.0.5",
|
|
"@eslint/js": "^10.0.1",
|
|
"@tailwindcss/vite": "^4.2.4",
|
|
"@types/benchmark": "^2.1.5",
|
|
"@types/d3": "^7.4.3",
|
|
"@types/ejs": "^3.1.5",
|
|
"@types/express": "^5.0.6",
|
|
"@types/hammerjs": "^2.0.46",
|
|
"@types/howler": "^2.2.12",
|
|
"@types/js-yaml": "^4.0.9",
|
|
"@types/msgpack5": "^3.4.6",
|
|
"@types/node": "^24.12.0",
|
|
"@types/pg": "^8.20.0",
|
|
"@types/seedrandom": "^3.0.8",
|
|
"@types/ws": "^8.18.1",
|
|
"@vitest/coverage-v8": "^4.1.5",
|
|
"@vitest/ui": "^4.1.5",
|
|
"autoprefixer": "^10.5.0",
|
|
"benchmark": "^2.1.4",
|
|
"canvas": "^3.2.3",
|
|
"concurrently": "^9.2.1",
|
|
"cross-env": "^10.1.0",
|
|
"d3": "^7.9.0",
|
|
"eslint": "^10.3.0",
|
|
"eslint-config-prettier": "^10.1.8",
|
|
"eslint-formatter-gha": "^2.0.1",
|
|
"glob": "^13.0.6",
|
|
"globals": "^17.6.0",
|
|
"husky": "^9.1.7",
|
|
"jsdom": "^29.1.1",
|
|
"lint-staged": "^16.4.0",
|
|
"lit": "^3.3.2",
|
|
"marked": "^18.0.5",
|
|
"mrmime": "^2.0.1",
|
|
"pixi-filters": "^6.1.5",
|
|
"pixi.js": "^8.18.1",
|
|
"prettier": "^3.8.3",
|
|
"prettier-plugin-organize-imports": "^4.3.0",
|
|
"prettier-plugin-sh": "^0.18.1",
|
|
"tailwindcss": "^4.2.4",
|
|
"tsconfig-paths": "^4.2.0",
|
|
"typescript": "^6.0.3",
|
|
"typescript-eslint": "^8.59.1",
|
|
"vite": "^8.0.10",
|
|
"vite-plugin-html": "^3.2.2",
|
|
"vitest": "^4.1.5",
|
|
"vitest-canvas-mock": "^1.1.4"
|
|
},
|
|
"dependencies": {
|
|
"@lit-labs/virtualizer": "^2.1.1",
|
|
"@opentelemetry/api": "^1.9.1",
|
|
"@opentelemetry/api-logs": "^0.216.0",
|
|
"@opentelemetry/exporter-logs-otlp-http": "^0.218.0",
|
|
"@opentelemetry/exporter-metrics-otlp-http": "^0.218.0",
|
|
"@opentelemetry/resources": "^2.7.1",
|
|
"@opentelemetry/sdk-logs": "^0.216.0",
|
|
"@opentelemetry/sdk-metrics": "^2.7.1",
|
|
"@opentelemetry/semantic-conventions": "^1.40.0",
|
|
"@opentelemetry/winston-transport": "^0.26.0",
|
|
"@types/compression": "^1.8.1",
|
|
"colord": "^2.9.3",
|
|
"compression": "^1.8.1",
|
|
"dompurify": "^3.4.2",
|
|
"dotenv": "^17.4.2",
|
|
"ejs": "^5.0.2",
|
|
"express": "^5.2.1",
|
|
"express-rate-limit": "^8.5.1",
|
|
"fastpriorityqueue": "^0.8.0",
|
|
"howler": "^2.2.4",
|
|
"intl-messageformat": "^11.2.3",
|
|
"ip-anonymize": "^0.1.0",
|
|
"jose": "^6.2.3",
|
|
"js-yaml": "^4.1.1",
|
|
"lil-gui": "^0.21.0",
|
|
"limiter": "^3.0.0",
|
|
"nanoid": "^5.1.11",
|
|
"node-html-parser": "^7.1.0",
|
|
"obscenity": "^0.4.6",
|
|
"seedrandom": "^3.0.5",
|
|
"ts-node": "^10.9.2",
|
|
"tsx": "^4.21.0",
|
|
"winston": "^3.19.0",
|
|
"ws": "^8.20.1",
|
|
"zod": "^4.4.2"
|
|
},
|
|
"overrides": {
|
|
"sanitize-html": ">=2.17.4"
|
|
},
|
|
"type": "module"
|
|
}
|