nodejs

Verified·Scanned 2/18/2026

This skill is a Node.js best-practices guide covering event loop, async errors, ESM, environment variables, memory leaks, and streams. It explicitly instructs loading environment files via dotenv.config() and accessing process.env (e.g., PORT), which involves reading .env files.

from clawhub.ai·vcc7d0aa·2.7 KB·0 installs
Scanned from 1.0.0 at cc7d0aa · Transparency log ↗
$ vett add clawhub.ai/ivangdavila/nodejs

Event Loop

  • fs.readFileSync blocks entire server — use fs.promises.readFile or callback version
  • CPU-intensive code blocks — offload to worker threads or child process
  • setImmediate vs process.nextTick — nextTick runs before I/O, setImmediate after
  • Long-running loops starve I/O — break into chunks with setImmediate

Async Error Handling

  • Unhandled promise rejection crashes in Node 15+ — always .catch() or try/catch with await
  • process.on('unhandledRejection') for global handler — log and exit gracefully
  • Errors in callbacks need explicit handling — won't propagate to outer try/catch
  • Promise.all fails fast — one rejection rejects all, use Promise.allSettled if need all results

CommonJS vs ESM

  • "type": "module" in package.json for ESM — otherwise .mjs extension
  • ESM: import x from 'y' — CommonJS: const x = require('y')
  • No __dirname in ESM — use import.meta.url with fileURLToPath
  • Can't require() ESM modules — use dynamic import() which returns Promise
  • exports is reference to module.exports — reassigning exports = x breaks it

Environment Variables

  • process.env values are always strings — PORT=3000 is "3000" not 3000
  • Missing env var is undefined, not error — check explicitly or use defaults
  • .env files need dotenv — not built-in, call dotenv.config() early
  • Don't commit .env — use .env.example with dummy values

Memory Leaks

  • Event listeners accumulate — removeListener when done, or use once
  • Closures capturing large objects — nullify references when done
  • Global caches grow unbounded — use LRU cache with size limit
  • --max-old-space-size to increase heap — but fix leaks first

Streams

  • Backpressure: write() returns false when buffer full — wait for drain event
  • .pipe() handles backpressure automatically — prefer over manual read/write
  • Error handling on all streams — stream.on('error', handler) or pipeline errors silently
  • pipeline() over .pipe() — handles errors and cleanup properly

Common Mistakes

  • JSON.parse throws on invalid JSON — wrap in try/catch
  • require() is cached — same object returned on repeated calls
  • Circular dependencies partially work — but export may be incomplete at require time
  • async function always returns Promise — even if you return plain value
  • Buffer.from(string) encoding matters — default is UTF-8, specify if different