CalcSnippets Search
JavaScript 3 min read

Node.js ESM vs CommonJS: A Practical Migration Guide

Understand the differences between ESM and CommonJS in Node.js and plan a practical migration that avoids broken imports and tooling surprises.

ESM and CommonJS are not only syntax choices

Node.js has supported CommonJS for a long time, and much of the ecosystem still uses it. ECMAScript Modules, usually called ESM, are the standard JavaScript module system used in browsers and modern tooling. Migrating from CommonJS to ESM can make a project more aligned with current JavaScript, but it can also create friction if imports, exports, package settings, and build tools are not handled carefully.

CommonJS uses require() and module.exports. ESM uses import and export. The syntax difference is easy to see, but the runtime behavior also differs. ESM is loaded asynchronously, has stricter static structure, and handles default exports differently. Code that looks mechanically convertible may still behave differently after migration.

Package settings control how files are interpreted

The package.json type field is a key decision. If "type": "module" is set, .js files are treated as ESM by default. If omitted or set to "commonjs", .js files are treated as CommonJS. File extensions can override this: .mjs is ESM and .cjs is CommonJS. For gradual migration, some teams use .mjs or .cjs strategically instead of flipping the entire package at once.

Imports require more precision in ESM. Relative imports usually need full file extensions, such as ./utils.js. Directory imports and implicit index resolution may not work the same way. This surprises teams that are used to bundlers resolving paths automatically. Before migrating, run the code in the same environment that production uses, not only through a development server.

  • Audit entry points, imports, dependencies, and build tools before switching formats.
  • Use file extensions deliberately during gradual migrations.
  • Test external dependencies because ESM and CommonJS interop can be uneven.
  • Treat package module format as part of the public contract.

Interoperability and tooling need testing

Interoperability is possible but not invisible. ESM can import many CommonJS modules, but named exports may not behave as expected. CommonJS can load ESM only through dynamic import() in many cases. If your project depends on older packages, test them early. If your package is consumed by others, think carefully before publishing an ESM-only release because some downstream users may still rely on CommonJS.

Tooling should be audited before the migration. Test runners, linters, transpilers, TypeScript settings, bundlers, and deployment platforms may all need configuration changes. TypeScript projects should review module, moduleResolution, and package export settings. A migration that only updates source files but ignores tooling will likely fail in CI.

Migrate with a clear boundary

Package exports are worth understanding. The exports field in package.json controls what paths consumers can import. It can provide separate ESM and CommonJS entry points, but dual packages add complexity. If you maintain a library, test both import styles and document supported usage clearly. Avoid exposing deep internal paths unless you are willing to support them.

A practical migration plan starts with inventory. Identify entry points, internal imports, external dependencies, build steps, tests, and consumers. Convert a small boundary first, such as a CLI entry or a new package in a monorepo. Keep automated tests running after each step. For applications, migration can be more direct because you control the runtime. For libraries, compatibility deserves more caution.

ESM is the long-term direction for JavaScript modules, but CommonJS is not instantly obsolete. The right approach is pragmatic: migrate when it improves compatibility, tooling, or maintainability, and do it with a clear test plan. Treat module format as part of your public contract, not just a syntax preference.

Keep reading

Related guides