← Back to Usage Guide Index
ModuleManager lets you dynamically import() JavaScript modules at runtime and access their exports through a small registry keyed by your own IDs.
- Loads ES modules from URLs and returns the module namespace (default + named exports).
- Associates a module with your chosen
idso call sites stay short and readable. - Caches modules by
idto avoid duplicate fetch/parse work in a session.
Use this when you want feature packs, tools, or plugins that can be fetched lazily.
// Load once, then use
const math = await net.modules.load("mathTools", "/modules/math.js");
console.log("2 + 3 =", math.add(2, 3));
// Somewhere else (later) — load with the same id
const math2 = await net.modules.load("mathTools", "/modules/math.js");
// Typically returns the cached namespaceYour module can export anything valid in ESM:
// /modules/math.js
export function add(a, b) { return a + b; }
export const PI = 3.14159;
export default { add };id: unique string key for the module.url: absolute or relative path to an ES module.- Returns: the module namespace object (e.g.,
{ default, add, PI }). - Caching: loading the same
id(and typically the same URL) returns the already‑resolved namespace.
Keep
idstable per capability (e.g.,"csvTools","sceneChess"), not per call site.
Browser module caches and registries are sticky by design. Common patterns:
-
Version the URL:
await net.modules.load("mathTools", "/modules/math.js?v=2");
-
Use build/commit hashes in the path (e.g.,
/modules/calc.9f3c1.js). -
Explicit rename the
idfor a new major version (e.g.,mathToolsV2).
Hard reloading the same URL is generally not supported by browsers once imported; prefer versioned URLs.
Wrap loads to surface network/parse errors clearly:
try {
const mod = await net.modules.load("charts", "/modules/charts.js");
mod.render("#root");
} catch (e) {
console.error("Module load failed", { id: "charts", err: e });
}Common causes:
- 404/500 from the module URL
- Non‑ESM sources (UMD/CommonJS) — ensure
exportsyntax - CORS blocked for cross‑origin URLs
- MIME type issues on servers (serve as
text/javascriptor a JS‑compatible type)
- Trust boundary: remote modules execute code — treat them as untrusted unless you control the origin.
- CSP: use a Content‑Security‑Policy that restricts
script-srcto allowed hosts. - SRI: if you serve static modules, consider Subresource Integrity for tamper detection.
- Dependency hygiene: prefer pinning/locking versions of third‑party modules.
- Deferred features: load heavy tools only when needed (editor panes, data viz, rare dialogs).
- Split by capability: keep module namespaces small and intention‑revealing (e.g.,
imageTools,authUI). - Top‑level await: supported in ESM; your module can
awaitduring initialization if necessary. - Side‑effects: avoid module‑level side‑effects; export explicit setup functions for predictable lifecycles.
- "Cannot use import statement outside a module" → The file isn’t served/parsed as ESM. Ensure correct MIME type and no transpiled CommonJS.
- CORS errors → Host on the same origin or enable CORS for the app’s origin.
- Relative import failures inside the module → Ensure the module’s own
importstatements use valid relative paths from its served location. - Cache confusion → Append a version query (
?v=...) or change the filename when publishing updates.
- SPEC_MANAGER.md — spec‑driven API calls.
- BATCHING_AND_COORDINATION.md — load accompanying configs/assets alongside modules.
- AUTHENTICATION_AND_SECURITY.md — CORS, credentials, and headers.