JavaScript modules let you split a program into files with explicit dependencies: a module exports values, and another imports the values it needs. ES modules (ESM) are JavaScript’s standardized module format, but the rules for finding a module file depend on where the code runs. In particular, browser and bundler imports do not necessarily follow Node.js’s file-resolution rules.
What is a JavaScript module?
A module is a unit of JavaScript code that can share selected values with other modules. Its exports form an interface; code that is not exported remains private to that module. This lets a project divide responsibilities across files without putting every function and variable into one shared global scope.
ES modules use the export and import keywords. The language defines their syntax and semantics, but the host environment—such as a browser or Node.js—determines how an import specifier is resolved to a file or package. The TypeScript Handbook’s module theory explains this host-defined part of module behavior.
How do named imports and exports work?
A named export makes a particular binding available by name. The importing module requests that same name inside braces.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
#1 Best Overall
// math.js
export function add(a, b) {
return a + b;
}
// app.js
import { add } from './math.js';
console.log(add(2, 3)); // 5
Here, add is a named export. The relative specifier ./math.js identifies the module to load; whether its extension is required depends on the host. The example’s extension is valid for Node.js ESM and is also a clear choice in environments that accept it.
A module can expose multiple named exports, and an importer can request more than one:
// numbers.js
export const answer = 42;
export function double(value) {
return value * 2;
}
// app.js
import { answer, double } from './numbers.js';
Names must match the exported bindings unless the importer uses an alias, such as import { double as twice } from './numbers.js';.
How is a default export different?
A default export is a separate export form, not an inherently better version of a named export. A module can have one default export, and the importing code chooses its local name without braces.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Rank #2
// formatter.js
export default function format(value) {
return String(value).trim();
}
// app.js
import clean from './formatter.js';
Use named exports when consumers should refer to specific exported names; use a default export when the module is naturally represented by one primary value. An import can combine a default import and named imports when a module provides both.
When should you use static import or dynamic import()?
A static import declaration belongs at a module’s top level. It makes the dependency explicit in the module source:
import { add } from './math.js';
Use dynamic import() when loading should happen asynchronously or conditionally, for example after a user chooses a feature:
if (showAdvancedTools) {
const tools = await import('./advanced-tools.js');
tools.open();
}
Dynamic import returns a promise. It is useful for conditional loading, but it should not be presented as an automatic performance improvement: the effect depends on the runtime and build setup.
How do you use ES modules in Node.js?
Node.js supports both ESM and CommonJS. Make the intended format explicit where possible; the Node.js ECMAScript modules documentation describes these markers and current syntax detection behavior.
| Format | Common markers |
|---|---|
| ES modules | .mjs, or .js files in a package whose package.json sets "type": "module" |
| CommonJS | .cjs, or .js files in a package whose package.json sets "type": "commonjs" |
Node.js also supports input-type flags for code supplied through standard input or evaluated directly: --input-type=module selects ESM, while --input-type=commonjs selects CommonJS. If no explicit marker is present, current Node.js documentation also describes syntax detection; explicit markers make a project’s intent easier to see.
Include extensions in Node.js relative imports
For Node.js ESM, relative and absolute specifiers must include the file extension. Directory index files must also be specified fully. For example, use ./utils.js, not ./utils or ./utils/. These are Node.js resolution rules, not universal rules for browsers or bundlers.
// Node.js ESM
import { parse } from './utils/parse.js';
If an import works through a bundler but fails when running the emitted file directly in Node.js, check whether the specifier follows Node’s extension and package-resolution rules.
Rank #4
Understand package specifiers and exports
Node.js accepts relative specifiers such as ./startup.js, bare package specifiers such as some-package, and absolute URL specifiers. A package’s exports field can restrict which package subpaths consumers are allowed to import. A file existing inside a package does not by itself mean that consumers may import it through any path.
How does Node.js handle CommonJS interop?
Node.js ESM can import CommonJS modules. The reliable form is a default import: that default corresponds to the CommonJS module’s module.exports value.
// ESM file importing a CommonJS package
import legacyPackage from 'legacy-package';
Node.js may also make some CommonJS exports available as named imports through static analysis. This is best-effort rather than a guarantee: some export patterns may not be detected, and inferred named exports do not reflect later changes to the CommonJS exports object. Use the default import when dependable access to module.exports is needed.
Node.js require() supports only synchronous ES modules. An ES module that uses top-level await cannot be loaded that way. Interoperability behavior can differ among Node.js, browsers, bundlers, transpilers, and TypeScript, so avoid assuming one environment’s rules apply everywhere.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallCrashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteBest Value
How should TypeScript module settings match the runtime?
TypeScript’s module configuration and module-resolution configuration describe how the compiler should model the environment that will execute the code. They do not make every runtime resolve files the same way. Choose settings for the actual destination rather than treating one configuration as universal.
Code intended to run in Node.js
The current TypeScript Modules Reference recommends the node16, node18, or nodenext module modes for Node.js projects. These modes model Node’s dual ESM/CommonJS system and select behavior based on each file’s detected format. They do not mean “ESM only”; TypeScript can emit ESM or CommonJS according to that format.
Code processed by a bundler
For code a bundler processes, TypeScript documents bundler-oriented module resolution. Set module and moduleResolution to reflect the actual pipeline—especially whether the bundler processes TypeScript source directly or whether emitted JavaScript is later run by Node.js. A configuration that models a bundler may not accurately model direct Node.js execution.
Quick Recap
Practical checks when an import fails
- Identify the host. Determine whether the code runs in a browser, Node.js, or through a bundler or transpiler.
- Check the file’s module format. In Node.js, look for
.mjsor the nearest package’s"type"setting; CommonJS can use.cjsor"type": "commonjs". - Check the specifier. For Node.js ESM relative imports, include the extension and any directory index filename.
- Check the package’s public paths. A package’s
exportsfield may block a subpath that appears to exist in its files. - Check import form and exported names. Named imports must refer to named exports; for a CommonJS module in Node.js, the default import is the dependable form.
- Align TypeScript with execution. Confirm that its module and resolution settings represent the runtime or bundler that actually handles the code.
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.
Free tools Windows power users keep installed
One-click scans. No signup required.




