First, the hazard described in the previous section occurs when a package
contains both CommonJS and ES module sources and both sources are provided for
use in Node.js, either via separate main entry points or exported paths. A
package might instead be written where any version of Node.js receives only
CommonJS sources, and any separate ES module sources the package might contain
are intended only for other environments such as browsers. Such a package
would be usable by any version of Node.js, since import
can refer to CommonJS
files; but it would not provide any of the advantages of using ES module syntax.
A package might also switch from CommonJS to ES module syntax in a breaking change version bump. This has the disadvantage that the newest version of the package would only be usable in ES module-supporting versions of Node.js.
Every pattern has tradeoffs, but there are two broad approaches that satisfy the following conditions:
- The package is usable via both
require
andimport
. - The package is usable in both current Node.js and older versions of Node.js that lack support for ES modules.
- The package main entry point, e.g.
'pkg'
can be used by bothrequire
to resolve to a CommonJS file and byimport
to resolve to an ES module file. (And likewise for exported paths, e.g.'pkg/feature'
.) - The package provides named exports, e.g.
import { name } from 'pkg'
rather thanimport pkg from 'pkg'; pkg.name
. - The package is potentially usable in other ES module environments such as browsers.
- The hazards described in the previous section are avoided or minimized.