SystemJS
A hookable, standards-based module loader that runs System.register modules and import maps in browsers back to IE11.
Repository Health
Technical Analysis
SystemJS is a dynamic module loader that runs code written in the System.register format across modern and legacy browsers alike, supporting live bindings, circular references, dynamic import, top-level await, and import maps back to IE11. It ships as three purpose-built builds: a 2.8KB s.js loader for minimal production footprints, a 4.2KB system.js loader with tracing hooks and pluggable module type support (CSS, JSON, Wasm), and a system-node.cjs build for running System modules server-side in Node.js SSR workflows.
Because every loader hook is overridable, SystemJS underpins several other tools rather than competing with them directly: jspm.org uses it as the backwards-compatibility layer for its package manager, single-spa relies on it to load framework-agnostic microfrontends, and Rollup’s code-splitting output can target the System.register format directly for production-grade dynamic loading in older browsers.
What You Get
- Three loader builds (s.js, system.js, system-node.cjs) sized for different deployment targets, from a 2.8KB CSP-friendly loader to a full Node.js SSR loader
- Import maps support via
<script type="systemjs-importmap">, including scoped and dynamic import maps - Pluggable extras: AMD interop, named-register bundles, global-script loading, and CSS/JSON/Wasm module types
- Tracing hooks (System.onload) and a registry deletion API for hot-reload and reloading workflows
- IE11 compatibility for live bindings, circular references, and top-level await, given Promise/fetch polyfills
Common Use Cases
- Loading Rollup code-splitting builds in production without needing native ES module support
- Providing the backwards-compatibility loader beneath package managers like jspm
- Loading independently-deployed microfrontends framework-agnostically (single-spa)
- Server-side rendering System modules in Node.js via the system-node.cjs build
Under The Hood
Architecture SystemJS’s execution flow begins in System.import() (src/system-core.js), which resolves an id through the pluggable loader.resolve hook, creates or reuses a Load record, and drives it through instantiate/link/execute stages that support circular references, live bindings, and function hoisting; system-core.js intentionally ships with no resolve or instantiate implementation, deferring both to override points installed by other modules. Each capability — script/fetch loading, URL/import-map resolution, worker loading, dependency pre-caching, global-script interop, AMD, named-register, module-type parsing — lives in its own file under src/features/ or src/extras/ and simply monkey-patches methods onto the shared systemJSPrototype exported from system-core.js, so the three shipped builds (s.js, system.js, system-node.cjs) are just different combinations of these feature imports assembled by src/s.js, src/system.js, and src/system-node.js and bundled per target in chompfile.toml. This gives a genuinely pluggable, hook-based architecture with a clean core/feature separation, though it relies on global prototype mutation and Symbol-keyed instance state rather than explicit composition, so changing the shape of systemJSPrototype or the Load record in system-core.js would ripple through every feature file that patches it.
Tech Stack SystemJS ships zero runtime dependencies — package.json lists no dependencies, only devDependencies for the build/test pipeline (rollup@2, @rollup/plugin-json/node-resolve/replace, rollup-plugin-terser/terser@5 for minification, @vercel/ncc@0.34 to bundle the Node build, mocha@7 for tests, bluebird and whatwg-fetch/node-fetch as legacy-environment polyfills for testing IE11 code paths). All of it is orchestrated by Chomp (chompbuild.com) via chompfile.toml, which defines rollup targets per build (dist/system.js, dist/s.js, dist/extras/*.js as IIFE bundles with process.env.SYSTEM_PRODUCTION/SYSTEM_BROWSER replacements), a terser task for the .min.js/.map outputs (ES5 target, Safari 10 safe), and an ncc task that produces the single-file dist/system-node.cjs for Node.js SSR use. There is no TypeScript, no application framework, and no database — the entire deployment target is static browser/Node JS files published straight from dist/.
Code Quality Tests are split between Mocha-based unit tests (test/system-core.mjs, test/url-resolution.mjs, test/import-map.mjs, test/system-node.mjs, run via Node’s built-in assert module) and browser integration tests (test/browser/*.js, served through a custom test/server.mjs and loaded via test.html/test-base-href.html) covering AMD, dynamic import maps, named exports/register, and worker loading; CI (.github/workflows) runs on Windows and Ubuntu on every push/PR, plus a separate size-impact-reporting job. There is no TypeScript and no ESLint/Prettier config in the repo, so type safety and lint enforcement are absent; error handling instead centers on a small, deliberate convention (src/err-msg.js) that throws Error objects annotated with a stable numeric code and a link into docs/errors.md, letting production builds strip verbose messages (process.env.SYSTEM_PRODUCTION) while keeping errors traceable. Naming is terse and consistent with the vanilla ES5-target style (function-based prototypes, no classes), appropriate for a size-budgeted loader but not enforced by any static tooling.
API Design The public surface is deliberately small: System.import(), System.register(), and a handful of overridable hooks (resolve, instantiate, locate, fetch, createContext) that every extra and feature builds on rather than exposing a bespoke plugin API of its own. Getting started requires no build step at all — drop in a script tag and call System.import() — while advanced usage (custom hooks, import maps, module types) is documented with runnable HTML/JS snippets across docs/api.md, docs/hooks.md, docs/import-maps.md, and docs/system-register.md. The tradeoff for that minimalism is that error messages are terse numeric codes (errMsg) requiring a trip to docs/errors.md to fully diagnose, and there’s no TypeScript typings shipped in the package itself.
Used by 2 apps in this directory
Blinko
Knowledge Management · Note Taking
A self-hosted, AI-powered card note-taking tool that lets you capture fleeting thoughts instantly and retrieve them with natural language search.
Grafana
Monitoring · Analytics
The open-source observability platform that unifies metrics, logs, and traces from any data source into dynamic, queryable dashboards.