Use when building applications with Node.js, the most widely deployed JavaScript/TypeScript runtime. Covers the event loop, module system (CommonJS and ESM), core modules (fs, path, http, crypto, streams, worker_threads, child_process), async patterns, diagnostics, error handling, security, native addons, and TypeScript integration.
USE FOR: Node.js server-side development, HTTP servers and APIs, file system operations, streams and data processing, worker threads and parallelism, child process management, Node.js module system (CJS/ESM), event loop and async patterns, Node.js diagnostics and profiling, native addon development, Node.js TypeScript configuration, package.json exports field, Node.js 18/20/22+ features
DO NOT USE FOR: Deno-specific features or Deno Deploy (use deno), Bun-specific APIs, frontend-only browser code, Express/Fastify/NestJS framework details (use the respective package skills), package manager comparison (use package-management)
Instalar com Codex ou Claude Copie este prompt, cole no Codex, Claude ou outro assistente e deixe que ele revise a página da skill e instale para você.
Um comando direto ignora o prompt de revisão. Verifique a origem antes de executá-lo.
Use when building applications with Node.js, the most widely deployed JavaScript/TypeScript runtime. Covers the event loop, module system (CommonJS and ESM), core modules (fs, path, http, crypto, streams, worker_threads, child_process), async patterns, diagnostics, error handling, security, native addons, and TypeScript integration.
USE FOR: Node.js server-side development, HTTP servers and APIs, file system operations, streams and data processing, worker threads and parallelism, child process management, Node.js module system (CJS/ESM), event loop and async patterns, Node.js diagnostics and profiling, native addon development, Node.js TypeScript configuration, package.json exports field, Node.js 18/20/22+ features
DO NOT USE FOR: Deno-specific features or Deno Deploy (use deno), Bun-specific APIs, frontend-only browser code, Express/Fastify/NestJS framework details (use the respective package skills), package manager comparison (use package-management)
[{"title":"Node.js Documentation","url":"https://nodejs.org"},{"title":"Node.js GitHub Repository","url":"https://github.com/nodejs/node"},{"title":"Node.js API Documentation","url":"https://nodejs.org/docs/latest/api/"}]
Node.js
Overview
Node.js is the original and most widely deployed server-side JavaScript runtime. Built on the V8 engine, it uses an event-driven, non-blocking I/O model that makes it well suited for data-intensive real-time applications. Node.js has the largest ecosystem of any runtime via npm, with millions of packages, and is supported by virtually every cloud provider, CI/CD platform, and hosting service.
Node.js runs JavaScript natively and supports TypeScript through transpilation tools (tsx, ts-node, swc, esbuild) or, starting with Node 22+, experimental built-in type stripping via --experimental-strip-types.
Node.js Version Landscape
Version
Status
Key Features
18 LTS
Maintenance LTS (EOL April 2025)
Global fetch, Web Streams API, node --test runner, --watch mode, node: prefix for builtins, Blob and BroadcastChannel globals, V8 10.2
For production: Use the latest Active LTS release (currently Node 22 LTS or Node 20 LTS).
Even-numbered releases become LTS and receive 30 months of support.
Odd-numbered releases are Current (latest features) with a shorter support window.
Use nvm, fnm, volta, or mise to manage multiple Node.js versions per project.
Module System
Node.js supports two module systems: CommonJS (CJS) and ECMAScript Modules (ESM). Understanding when and how to use each is critical for modern Node.js development.
File extensions are mandatory in relative imports (.js, .mjs, .ts with loaders).
No __dirname or __filename -- use import.meta.dirname (Node 21+) or import.meta.url with fileURLToPath.
Default in files with .mjs extension or when package.json has "type": "module".
Top-level await is supported.
package.json type Field
{"type":"module"// Treat .js files as ESM// or"type":"commonjs"// Treat .js files as CJS (default if omitted)}
File Extension
"type": "module"
"type": "commonjs" (or omitted)
.js
ESM
CJS
.mjs
ESM
ESM
.cjs
CJS
CJS
.ts (with loader)
ESM
CJS
.mts (with loader)
ESM
ESM
.cts (with loader)
CJS
CJS
Conditional Exports (package.json exports Field)
The exports field in package.json defines the public API of a package and supports conditional resolution for different environments.
{"name":"my-library","type":"module","exports":{// Main entry point".":{"types":"./dist/index.d.ts",// TypeScript types (must be first)"import":"./dist/index.mjs",// ESM entry"require":"./dist/index.cjs",// CJS entry"default":"./dist/index.mjs"// Fallback},// Subpath export"./utils":{"types":"./dist/utils.d.ts","import":"./dist/utils.mjs","require":"./dist/utils.cjs"},// Subpath pattern (wildcard)"./components/*":{"types":"./dist/components/*.d.ts","import":"./dist/components/*.mjs","require":"./dist/components/*.cjs"},// Restrict access -- block deep imports"./internal/*":null,// package.json self-reference"./package.json":"./package.json"},// Fallback for older Node.js (pre-exports support)"main":"./dist/index.cjs","module":"./dist/index.mjs","types":"./dist/index.d.ts"}
Condition ordering matters. Node.js uses the first matching condition. Always place "types" first (for TypeScript), then "import", then "require", then "default".
Additional conditions:
Condition
Description
"node"
Node.js environment
"browser"
Browser bundlers (webpack, Vite)
"development"
Development mode
"production"
Production mode
"node-addons"
Native addon support required
"edge-light"
Edge runtime (Vercel Edge, Cloudflare)
Interoperability Between CJS and ESM
// ESM can import CJS modules directlyimport cjsModule from"./legacy-module.cjs";
// CJS can import ESM modules via dynamic importconst esmModule = awaitimport("./modern-module.mjs");
// Node 22+ with --experimental-require-module: CJS can require() ESM// Node 23+: require() of ESM is unflagged for synchronous ESM graphsconst esmModule = require("./modern-module.mjs");
Event Loop and Async Patterns
Event Loop Phases
The Node.js event loop processes callbacks in a specific order across multiple phases:
Worker threads enable true parallel computation by running JavaScript in separate V8 isolates with their own event loops, while sharing memory via SharedArrayBuffer.
// main.tsimport {
Worker, isMainThread, parentPort, workerData, MessageChannel
} from"node:worker_threads";
import { cpus } from"node:os";
if (isMainThread) {
// Main thread -- spawn workersconst numCPUs = cpus().length;
functionrunWorker(data: unknown): Promise<unknown> {
returnnewPromise((resolve, reject) => {
const worker = newWorker(newURL(import.meta.url), {
workerData: data,
});
worker.on("message", resolve);
worker.on("error", reject);
worker.on("exit", (code) => {
if (code !== 0)
reject(newError(`Worker exited with code ${code}`));
});
});
}
// Run computation across all CPUsconst tasks = Array.from({ length: numCPUs }, (_, i) => ({
start: i * 1_000_000,
end: (i + 1) * 1_000_000,
}));
const results = awaitPromise.all(tasks.map(runWorker));
console.log("Results:", results);
} else {
// Worker threadconst { start, end } = workerData as { start: number; end: number };
let sum = 0;
for (let i = start; i < end; i++) {
sum += i;
}
parentPort!.postMessage(sum);
}
import os from"node:os";
os.cpus(); // CPU info array
os.cpus().length; // Number of CPU cores
os.totalmem(); // Total memory in bytes
os.freemem(); // Free memory in bytes
os.platform(); // "linux", "darwin", "win32"
os.arch(); // "x64", "arm64"
os.hostname(); // Machine hostname
os.homedir(); // User home directory
os.tmpdir(); // Temp directory path
os.networkInterfaces(); // Network interface details
os.uptime(); // System uptime in seconds
os.type(); // "Linux", "Darwin", "Windows_NT"
# .env file format (supported by --env-file)PORT=3000DATABASE_URL=postgres://localhost:5432/mydb
API_KEY=sk-abc123
NODE_ENV=development
# Comments are supportedMULTILINE="line1\nline2"
TypeScript Support
Experimental Type Stripping (Node 22+)
# Run TypeScript directly (strips types, no emit, no type checking)
node --experimental-strip-types app.ts
# With enums and namespaces (Node 23+)
node --experimental-transform-types app.ts
Limitations of --experimental-strip-types:
Only strips types; does not perform type checking (use tsc --noEmit separately).
Does not support TypeScript-specific emit features (enums, namespaces, decorators) without --experimental-transform-types.
Does not support paths in tsconfig (use subpath imports in package.json instead).
File extensions must be .ts, not .tsx (JSX requires a transform).
tsx (Recommended for Development)
# Install
npm install -D tsx
# Run TypeScript files
npx tsx app.ts
# Watch mode
npx tsx watch app.ts
# Use as Node.js loader
node --import tsx app.ts
# Install
npm install -D ts-node typescript
# Run
npx ts-node app.ts
# With ESM
node --loader ts-node/esm app.ts
// tsconfig.json for ts-node with ESM{"compilerOptions":{"module":"NodeNext","moduleResolution":"NodeNext","target":"ES2022","esModuleInterop":true,"strict":true,"outDir":"./dist","rootDir":"./src"},"ts-node":{"esm":true,"transpileOnly":true}}
Recommended tsconfig.json for Node.js
// Node 20+ recommended tsconfig{"compilerOptions":{// Language and environment"target":"ES2022","lib":["ES2023"],"module":"NodeNext","moduleResolution":"NodeNext",// Strictness"strict":true,"noUncheckedIndexedAccess":true,"noImplicitOverride":true,"exactOptionalPropertyTypes":true,// Output"outDir":"./dist","rootDir":"./src","declaration":true,"declarationMap":true,"sourceMap":true,// Interop"esModuleInterop":true,"forceConsistentCasingInFileNames":true,"isolatedModules":true,"verbatimModuleSyntax":true,// Skip type checking node_modules"skipLibCheck":true},"include":["src/**/*"],"exclude":["node_modules","dist"]}
Diagnostics and Debugging
Inspector (--inspect)
# Start with debugger listening
node --inspect server.js # Listen on 127.0.0.1:9229
node --inspect=0.0.0.0:9229 server.js # Listen on all interfaces
node --inspect-brk server.js # Break on first line# Debug TypeScript with tsx
node --inspect --import tsx src/server.ts
Open chrome://inspect in Chrome, or connect from VS Code with a launch configuration:
# Build with node-gyp
npm install -g node-gyp
node-gyp configure
node-gyp build
# Use prebuild for precompiled binaries
npm install prebuild prebuild-install
npx prebuild -t 18.0.0 -t 20.0.0 -t 22.0.0
// Using a native addonconst addon = require("./build/Release/addon.node");
// Or with N-API node-addon-api (C++ wrapper):// const addon = require("bindings")("addon");const result = addon.heavyComputation(data);
When to use native addons:
CPU-intensive computation that cannot be efficiently parallelized with worker threads.
// Import using the # prefix (private, not exposed to consumers)import { connect } from"#db";
import { formatDate } from"#utils/date";
Best Practices
Use the latest Active LTS version for production. Enable automatic security updates or have a process to apply them promptly.
Use ESM for new projects. Set "type": "module" in package.json. Use .mjs/.cjs extensions only when mixing module systems within a single package.
Use node: prefix for built-in modules. Write import fs from "node:fs/promises" instead of import fs from "fs" to make it unambiguous that you are importing a built-in.
Use fs/promises instead of callback-based fs. The promise-based API integrates naturally with async/await and avoids callback hell.
Use stream/promises pipeline for composing streams. Always handle backpressure by using pipeline() instead of manual .pipe() chains.
Use AbortController for cancellation. Pass AbortSignal to fetch, child processes, streams, and timers to enable clean cancellation.
Always handle unhandledRejection and uncaughtException. Log the error, flush metrics, and exit the process. Do not attempt to continue running after uncaughtException.
Use AsyncLocalStorage for request-scoped context (request IDs, user context, tracing spans) instead of passing context through every function argument.
Use worker threads for CPU-intensive work. The main event loop should only handle I/O coordination. Offload heavy computation to worker threads.
Use --env-file (Node 20.6+) instead of the dotenv package for loading environment variables from .env files.
Configure the exports field in package.json for any published package. Include "types" conditions for TypeScript consumers and both "import" and "require" conditions for dual CJS/ESM support.
Use tsx for development and tsc (or a bundler) for production builds. Do not use ts-node in production due to startup overhead.
Enable --experimental-permission in Node 20+ for defense-in-depth in production environments where the application should not access arbitrary file system paths or spawn processes.
Use diagnostics_channel for lightweight instrumentation and observability. It has near-zero overhead when no subscribers are registered.
Prefer node --test for simple test suites that do not need a full framework. For complex projects, use Vitest or Jest with proper TypeScript support.
Use process.exit() sparingly. Prefer graceful shutdown by closing servers, database connections, and flushing logs before exiting. Listen for SIGTERM and SIGINT.
Set "engines" in package.json to declare the minimum Node.js version:
{"engines":{"node":">=20.0.0"}}
Profile before optimizing. Use --inspect, --prof, heap snapshots, and perf_hooks to identify actual bottlenecks rather than guessing.