ES Modules
Loading multiple files with native import resolution
nx.js resolves native ES module
import
statements at runtime, so you can ship an unbundled, multi-file app or
lazy-load modules on demand with dynamic import().
Static imports
Both static import and top-level await are supported. Specifiers are
resolved as URLs relative to the importing module:
import { greet } from './greet.js';
import { CONFIG } from '/config.js'; // absolute path
greet(CONFIG.name);export function greet(name) {
console.log(`Hello, ${name}!`);
}Dynamic imports
await import() works too, for lazy-loading code only when needed:
async function onLevelStart() {
const { loadLevel } = await import('./levels/level1.js');
loadLevel();
}Resolution rules
Module specifiers are resolved against the importing module's URL:
| Specifier | Example | Supported |
|---|---|---|
| Relative | ./util.js, ../lib/x.js | ✅ |
| Absolute path | /config.js | ✅ |
| Absolute URL | romfs:/x.js, sdmc:/x.js, nxjs:/x.js, file:/x.js | ✅ |
| Bare specifier | react, lodash | ❌ (throws) |
| Remote URL | https://…, data:… | ❌ (not yet supported) |
- There is no
node_modulesresolution or import maps — bare specifiers (likereact) throw. Use a bundler if you depend on npm packages. - Resolution is synchronous, so only mounted filesystem schemes work
(
romfs:,sdmc:,nxjs:,file:). Remotehttp(s):/data:imports are not supported. - JSON and other asset module types are not yet supported.
import.meta
Each module has an accurate import.meta:
console.log(import.meta.url); // the module's resolved URL
console.log(import.meta.main); // true only for the entrypointModule cache & cycles
Modules are cached by their resolved URL, so a shared dependency imported through multiple paths resolves to a single instance (giving referential stability), and import cycles are handled correctly.