Skip to content

Migrate to ES modules (script type="module") #5

Description

@joedickey

Problem

All client-side JS runs in global scope. app.js exposes ~50+ variables and functions as implicit globals (play, stop, isPlaying, grid, synth, filter, etc.). jam.js consumes them by name with no declared dependency.

Consequences:

  • No enforced module boundaries — any file can silently read/write any variable from any other file
  • Script load order in index.html is manually managed and fragile
  • IDE tooling (go-to-definition, find-all-references, safe rename) is blind to cross-file relationships
  • JamSync's typeof play === 'function' guards exist purely because there's no other way to express the dependency
  • Splitting app.js into smaller files in the future requires careful global-scope archaeology

Solution

Migrate to native ES modules — a browser-native feature, no bundler or build step required.

<!-- index.html — after -->
<script type="module" src="app.js"></script>
<!-- jam.js is imported by app.js, not loaded separately -->
// app.js — export what jam.js needs
export function play(step) { ... }
export function stop() { ... }
export { isPlaying, seqPosition };
// jam.js — import explicitly
import { play, stop, isPlaying, seqPosition } from './app.js';

Acceptance Criteria

  • index.html loads app.js with type="module"; jam.js is imported by app.js (or vice versa — establish one clear dependency direction)
  • All cross-file references use explicit import/export — no implicit globals between app.js and jam.js
  • The existing window.jamSession, window.jamSendTransport etc. public API is preserved for any external integrations
  • Vendor scripts (Tone.js, cytoscape.min.js, lz-string.min.js) are handled — either imported as modules if they support it, or loaded as non-module scripts before the module entry point
  • The app works identically in Chrome, Firefox, and Safari
  • No build step is introduced

Notes

Do this last — it's the highest-leverage change but also the widest diff. Issues #3 (JamSync transport interface) and any other refactors should land first so this migration starts from a cleaner baseline.

Vendor libraries may not be ES module compatible. Tone.js has an ES module build available via npm. lz-string has a UMD build that works as a module. cytoscape has an ES module build. Each may need to be re-vendored from their module-compatible release.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions