ERR_REQUIRE_ESM
Tags: esm, es6, require, import
Published: 2021-03-31 15:49:37

_To save anybody's googling time_

Once you update you package deps you may face with the error mentioned in this note title:
```js
Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: ~/projects/semantic-release-toolkit/node_modules/zz/cjs.js
require() of ES modules is not supported.
require() of ~/projects/semantic-release-toolkit/node_modules/zz/cjs.js from ~/projects/semantic-release-toolkit/tt.js is an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which defines all .js files in that package scope as ES modules.
Instead rename cjs.js to end in .cjs, change the requiring code to use import(), or remove "type": "module" from ~/projects/semantic-release-toolkit/node_modules/zz/package.json.
```
Even though your code stopped working, this issue has positive context: the future is coming and some of your project's deps has been shipped as [ES module](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules).

# What's wrong?
The short answer — es module brings top-level await, but `require` has no idea how to deal with it. Detailed explanation — [announcing a new --experimental-modules](https://nodejs.medium.com/announcing-a-new-experimental-modules-1be8d2d6c2ff).

# How to fix?
There're several strategies:
## 1. Follow the trend
Migrate to ES modules. Replace `require` with `import`.
```js
// before
const { sync } = require('read-pkg-up')
// after
import { readPackageUpSync } from 'read-pkg-up'
```
Publish as esm. Add a special instruction to `package.json`
```json
{
  "type": "module"
}
```
## 2. Stay on ES5
Wrap ES6 module(s) with [esm](https://github.com/standard-things/esm) adapter. Just like the documentation says:
```js
// read-pkg-up-wrapper.js
require = require('esm')(module, {
  mode: 'all',
  cjs: {
    ... //
  },
  force: false,
  cache: false,
  await: false
})
module.exports = require('read-pkg-up')
```
**NOTE** It's advisable to use patched `esm` that properly handles legacy (.js) extensions. See [esm/issues/868](https://github.com/standard-things/esm/issues/868) for details.
## 3. Take both. 
Provide [conditional export](https://nodejs.org/api/packages.html#packages_conditional_exports).
You're able to split your code into `esm` and `cjs` versions.
```json
// package.json
{
   ...
  "exports": {
    "import": "./es6entry.mjs",
    "require": "./es5entry.cjs"
  }
}
```
**NOTE** `.cjs/.mjs` file extension has matter.  
This approach requires that your code to be refactored in some way:
* Rewrite by hand with `require` and `import` syntax.
* Recompile (TypeScript) separately with `CommonJS` and `ES6` [`module` options](https://www.typescriptlang.org/tsconfig#module).
* Wrap one version inside the other.
    * es6 in es5 (std/esm) as mentioned above
    * [reexport es5 from es6](https://nodejs.org/api/packages.html#packages_approach_1_use_an_es_module_wrapper)
```js
import cjsModule from './index.cjs'
export const name = cjsModule.name
```
Conditional export is especially important for a situation when you're developing a package that needs ES6 deps, but its called by an external utility that uses legacy ES5 loading. For example, `some-semrel-plugin` depends from `read-pkg-up@8` (es6), and is being [invoked through `require`](https://github.com/semantic-release/semantic-release/blob/12337175c6069082443ca1a035e6b3072312aaea/lib/plugins/utils.js#L47) directive in `semantic-release`.

# Related refs
* [EcmaScript-CommonJS Module Interop: The Missing Manual](https://github.com/johnloy/esm-commonjs-interop-manual#differences)
* [Node Modules at War: Why CommonJS and ES Modules Can’t Get Along](https://redfin.engineering/node-modules-at-war-why-commonjs-and-es-modules-cant-get-along-9617135eeca1)
* [Get Ready For ESM](https://blog.sindresorhus.com/get-ready-for-esm-aa53530b3f77)
* [Pure ESM package](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c)
* [Migrating from CommonJS to ESM](https://dev.to/jldec/migrating-from-commonjs-to-esm-2p24)
* [esm/issues/868](https://github.com/standard-things/esm/issues/868)
* [cjs to esm](https://github.com/wessberg/cjstoesm)
* [https://stackoverflow.com/questions/57169793/error-err-require-esm-how-to-use-es6-modules-in-node-12](https://stackoverflow.com/questions/57169793/error-err-require-esm-how-to-use-es6-modules-in-node-12)
* [https://blog.logrocket.com/publishing-node-modules-typescript-es-modules/](https://blog.logrocket.com/publishing-node-modules-typescript-es-modules/)
* [https://blog.logrocket.com/es-modules-in-node-today/](https://blog.logrocket.com/es-modules-in-node-today/)