Module Resolution
Module resolution decides how TypeScript turns an import path like 'lodash' or './util.js' into an actual file on disk. Picking the wrong strategy is a top source of "works in editor, breaks in CI" pain.
The choices
| Setting | When to use |
|---|---|
"NodeNext" | Modern Node packages with proper exports (preferred). |
"Bundler" | Vite, esbuild, Webpack, Next.js, Astro. |
"Node10" | Legacy Node — old projects. |
"Classic" | Pre-Node module-style. Don't. |
NodeNext rules of the road
- Imports must include the file extension — but it's the output extension (
.js) even though source is.ts:
TS
import { foo } from './bar.js'; // source is bar.ts
import { x } from './sub/index.js';
- Honours
"exports"inpackage.json— same as Node itself. - Different CJS / ESM resolution depending on the package's own type.
Bundler rules
- You can omit extensions; the bundler fills them in.
- Honours
"imports","exports", plus aliasing. - Simpler in source — but only safe if you really use a bundler at build time.
resolveJsonModule
TS
// tsconfig: "resolveJsonModule": true import data from './fixtures/users.json'; const first = data[0].name; // typed as the literal shape of users.json
moduleSuffixes
For per-platform variants (.ios.ts, .web.ts):
tsconfig.json
{
"compilerOptions": {
"moduleSuffixes": [".web", ""]
}
}
baseUrl + paths — alias resolution
Pairs with paths from the previous lesson. Aliases resolve before module resolution does its normal lookup.
Tip: For modern Node, use
"module": "NodeNext" + "moduleResolution": "NodeNext". For Vite / Next / Astro / Remix, use "module": "ESNext" + "moduleResolution": "Bundler". Mixing strategies wastes a Friday.Example
Example
// 'NodeNext' (modern) — uses package.json exports
// 'Bundler' (Vite, esbuild) — relaxed, follows the bundler
// 'Node10' (legacy)
//
// resolveJsonModule — import data.json as a typed object
console.log('Pick NodeNext or Bundler for new projects');
Try it Yourself »
Exercise
Modern Node resolution mode.
"moduleResolution": "
"
PascalCase; eight chars.
Discussion
Loading…