How ES Modules are resolved from specifiers to actual files.
Relative Paths
import utils from './utils.js';
import config from '../config.js';
Absolute URLs (Browser)
import lodash from 'https://cdn.skypack.dev/lodash';
Bare Specifiers (Node.js)
import express from 'express';
import { readFile } from 'fs/promises';
Control which files are exposed from your package:
{
"exports": {
".": "./dist/index.js",
"./utils": "./dist/utils.js",
"./package.json": "./package.json"
}
}
Conditional Exports:
{
"exports": {
".": {
"import": "./dist/index.js",
"require": "./dist/index.cjs",
"types": "./dist/index.d.ts"
}
}
}
Unlike CommonJS, ES Modules require explicit file extensions:
❌ Won't Work
import utils from './utils';
✅ Correct
import utils from './utils.js';