Busca en todas las páginas de la documentación
8 examples to get you started with Modules - 6 basic and 2 intermediate.
"type": "module" in package.json for ESM examples.Named exports are statically analyzable - the preferred default in 2026.
// user.ts
export interface User { id: string; name: string }
export function formatUser(u: User): string {
return `${u.name} (${u.id})`;
}// main.ts
import { formatUser, type User } from './user.js';
const user: User = { id: '1', name: 'Ada' };
console.log(formatUser(user));.js extensions in import specifiers when compiling TypeScript to ESM.import type erases at compile time - no runtime cost.Related: ES Modules (import) - dynamic import and TLA
One default export per module - use for single-purpose entry points.
// logger.ts
export default function createLogger(prefix: string) {
return (msg: string) => console.log(`[${prefix}]`, msg);
}import createLogger from './logger.js';
const log = createLogger('api');
log('started');Brownfield code still uses require - know it for maintenance.
// legacy.cjs
const path = require('node:path');
module.exports = {
basename: (p) => path.basename(p),
};const { basename } = require('./legacy.cjs');.cjs extension forces CommonJS even when "type": "module".require is synchronous - no top-level await in CJS modules.Related: CommonJS (require) - module.exports patterns
Sets ESM as default for .js files in the package.
{
"name": "billing-api",
"type": "module",
"exports": {
".": "./dist/index.js"
}
}"type": "module", .js files are treated as CommonJS."type": "commonjs" is explicit legacy mode."exports" for public entry points.Related: package.json type & exports - conditional exports
Clarify built-in imports and avoid user package shadowing.
import { readFile } from 'node:fs/promises';
import { createServer } from 'node:http';node: prefix is optional but recommended in application code.fs package from hijacking imports.require('node:fs')).Load modules conditionally or at runtime - returns a Promise.
async function loadPlugin(name: string) {
const mod = await import(`./plugins/${name}.js`);
return mod.default();
}
await loadPlugin('metrics');Related: ES Modules (import) - top-level await with dynamic import
Re-export a curated surface from index.ts.
// src/services/index.ts
export { UserService } from './user-service.js';
export type { User } from './user-service.js';import { UserService, type User } from './services/index.js';Related: Module Resolution Algorithm - how index resolves
Mixed modules during migration - explicit extensions and createRequire.
// bridge.mjs
import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);
const legacy = require('./legacy-config.cjs');
console.log(legacy.apiUrl);createRequire loads CJS from ESM context during brownfield migration.import and require paths in CI during transition.Related: CJS ↔ ESM Interop - dual packages and .mjs/.cjs
Stack versions: This page was written for Node.js 24.18.0 (Active LTS), npm 10+, TypeScript 5.6+, Express 5, Fastify 5, and NestJS 11.