Follow-up to #328 (Lost Fleet merge). The repo should move to ESM throughout. Today:
- The engine is CommonJS (
tsc → dist/, consumed by the BGS game-server via dynamic import(), which already supports ESM).
- The viewer builds with vue-cli 4 / webpack 4 / ts-loader 6, and compiles the engine's sources directly. This pipeline is also the root cause of the CJS/ESM default-import interop bugs that broke the published UMD bundle (worked around by vendoring
assert / shuffle-seed in engine/src/utils/).
Constraint / sequencing
True engine ESM ("type": "module" + module: NodeNext) requires .js extensions on ~200 relative imports — which ts-loader 6 / webpack 4 cannot resolve when compiling engine sources for the viewer. So the migration has to happen in this order:
1. Viewer → Vite
- Replace vue-cli 4 / webpack 4 with Vite +
@vitejs/plugin-vue2 (Vue 2.7 already in use; class components are supported).
- Keep the two build targets: dev app (
dist/app) and the self-contained UMD/IIFE lib built from src/wrapper.ts (dist/package, gaiaViewer global, bootstrap-vue external, svg assets inlined).
- Replace mochapack with vitest (or keep mocha via vite-node). ~810 existing specs must keep passing.
- Bonus: kills the pinned TypeScript 3.9/4.9 skew and the
tsconfig.build.json transpile-only workarounds.
2. Engine → ESM
"type": "module", module/moduleResolution: NodeNext, .js extension rewrite on relative imports (mechanical).
- Mocha → ESM runner (
mocha --loader=ts-node/esm or vitest), update prepublishOnly.
- Verify the BGS game-server loads
dist/wrapper.js as ESM (it JSON-round-trips results already, and the entry is loaded with dynamic import()).
- Drop the remaining CJS-only dep quirks (
seedrandom interop shim in src/utils/shuffle.ts can become a plain default import).
3. Cleanup enabled by the above
- Remove the interop-proof import shims and
tsconfig.build.json special-casing.
- Consider excluding
src/ai/ + src/fuzz/ from the published engine tarball (files), they are dev-only.
- Prune the now-moot
statistics=charts preference from the BGS game doc (stats window is table-only).
Since engine 4.10+ we are allowed to break seed/replay compat if it ever helps (v3 beta has no games), but the vendored shuffle is byte-identical anyway, so nothing forces it.
Follow-up to #328 (Lost Fleet merge). The repo should move to ESM throughout. Today:
tsc→dist/, consumed by the BGS game-server via dynamicimport(), which already supports ESM).assert/shuffle-seedinengine/src/utils/).Constraint / sequencing
True engine ESM (
"type": "module"+module: NodeNext) requires.jsextensions on ~200 relative imports — which ts-loader 6 / webpack 4 cannot resolve when compiling engine sources for the viewer. So the migration has to happen in this order:1. Viewer → Vite
@vitejs/plugin-vue2(Vue 2.7 already in use; class components are supported).dist/app) and the self-contained UMD/IIFE lib built fromsrc/wrapper.ts(dist/package,gaiaViewerglobal, bootstrap-vue external, svg assets inlined).tsconfig.build.jsontranspile-only workarounds.2. Engine → ESM
"type": "module",module/moduleResolution: NodeNext,.jsextension rewrite on relative imports (mechanical).mocha --loader=ts-node/esmor vitest), updateprepublishOnly.dist/wrapper.jsas ESM (it JSON-round-trips results already, and the entry is loaded with dynamicimport()).seedrandominterop shim insrc/utils/shuffle.tscan become a plain default import).3. Cleanup enabled by the above
tsconfig.build.jsonspecial-casing.src/ai/+src/fuzz/from the published engine tarball (files), they are dev-only.statistics=chartspreference from the BGS game doc (stats window is table-only).Since engine 4.10+ we are allowed to break seed/replay compat if it ever helps (v3 beta has no games), but the vendored shuffle is byte-identical anyway, so nothing forces it.