Therefore, when it is possible to not break practical code, it should not be done. This is the "linux philosophy", if you will. Among JS runtimes, Bun is a great example. In bun today, you can, in the same file (!!), with zero code changes, 100% transparently:
1. require() a module regardless of whether it is cjs or esm [1]
2. synchronously `import` a module regardless of whether it is cjs or esm.
3. do either of this with typescript or javascript
Some of these required changes in JavascriptCore, which were implemented - it's good to see a lack of cribbing about "it needs to be supported in upstream" and a focus on practical end-user usage.
Any runtime/kernel that doesn't put this level of effort into not breaking code is just not serious. While Node is at least moving in the right direction, supporting require(esm) with some restrictions, Deno is completely hopeless - CJS code is completely unusable on Deno. The reasoning is crazy too - how does it matter if ESM is the "standard", if millions of lines of practical, real world code is using CJS? It does not matter that popular libraries move to ESM. Even a single internal tool that's locked into CJS for some reason means that a project cannot move away from it easily. Then like someone mentioned below, many "plugin architectures" and "command architectures" are pretty much locked in to require(). The whole Deno project screams "ideology > pragmatism". Hopefully, just like they came to their senses w.r.t node compat [2], they implement CJS interop as well.
[1] You cannot require() an ESM module that uses top level await
[2] In contrast, bun's node compat story is very good, they run the Node.js test suite on every commit to Bun, and pass a huge majority of the test cases. Track the progress here: https://bun.sh/docs/runtime/nodejs-apis
There is even some effort put into V8 APIs(in a JSC runtime!!). This helps with using Bun with the usual debugger in the chrome browser/VSCode, modules that use `node:v8`, etc,. Read about it here: https://bun.sh/blog/how-bun-supports-v8-apis-without-using-v...
There is also compat the other way - there are the beginnings of node/browser polyfills for Bun-only APIs: https://github.com/oven-sh/bun/tree/main/packages/bun-polyfi...