Modules, Runtime & Tooling

ESM, CommonJS & Module Interop

ES modules are the JavaScript standard module system, while CommonJS is Node's older module format. Interop depends on runtime rules, package metadata, file extensions, compiler options, and bundler behavior.
  • ESM uses static import/export syntax
  • CommonJS uses runtime require/module.exports
  • Package type and file extension matter
  • Default import interop is a footgun
  • Libraries have harder compatibility choices than apps
Module systems
SystemSyntaxResolution/behavior
ESMimport/exportStandard, static, async-capable loading
CommonJSrequire/module.exportsNode legacy, dynamic
Dual packageExports ESM and CJSConsumer compatibility, more complexity
Bundler outputTool-generatedMay hide runtime details until publishing
ESM vs CommonJS
// ESM
export function parse(input) {
  return JSON.parse(input)
}

import { parse } from "./parse.js"

// CommonJS
module.exports = { parse }
const { parse } = require("./parse")
Similar intent, different runtime/module-system rules.
Sources
  • Node.js Documentation and Learn Node.jsModules
  • MDN JavaScript Guide and ReferenceJavaScript modules
  • TypeScript ReferenceModule resolution