I’ll conclude with three guidelines for library authors to follow:

Provide a CJS version of your library

Provide a thin ESM wrapper for your CJS

Add an exports map to your package.json

This seems like the same fallacy of python’s 2to3, and why they should have written 3to2 instead. If ESM is the new way, library authors should instead have a CJS shim to prevent fossilization of cruft.

> should instead have a CJS shim

OP wrote, note that it’s easy to write an ESM wrapper for CJS libraries, but it’s not possible to write a CJS wrapper for ESM libraries.

It's not possible to write a nice automated transparent one for arbitrary libraries because of top level await, but it's totally possible for the 95%.

You cannot write a CJS shim for any library because the CJS shim cannot expose any ESM file with a synchronous API because importing ESM always returns a Promise.

You can - and people widely do - compile a CJS version of your library from ESM sources. You'll accept that there may be multiple copies of your library in the program but it does work. But in any case there's no reason to actually author in CJS, everything including the ESM shim can be generated from ESM.

It is possible, but you have to hack the Node require() loader to do it, teach it a lot about ESM loading, and then hope the downstream CJS don't have timing bugs around "very long" synchronous require() loads.

https://github.com/standard-things/esm