Live data from Hacker News

Node Modules at War: Why CommonJS and ES Modules Can’t Get Along

redfin.engineering

111–120 of 152 posts

Re: Node Modules at War: Why CommonJS and ES Modules Can’t Get Along

#111

it seems so insane that there are competing module patterns in a single language, but perhaps i'm ignorant. are there other languages with such incompatibilities on a fundamental component?

`require()` isn't really a part of the language. It was a library added by nodejs, since javascript had no way of expressing modularity at all at the time.

Re: Node Modules at War: Why CommonJS and ES Modules Can’t Get Along

#112
post #102

Earlier quoted context omitted.

I'm pretty sure services like pika.dev/skypack.dev/jspm.io are trying to solve the CJS to ESM problem so you can use it directly in the browser (or deno). Last time I checked they seemed to lean into using rollup to take care of the translation under the covers.

That's not the point here. It's about that a thin CJS wrapper to an ESM module isn't possible but the way around is.

Sorry I misread your comment. But is it not easier to write an CJS wrapper around ESM given that its format is a lot looser?

From what I have seen seems pretty typical to simply export the named properties using a fresh module.exports = {...} and then use default as the main export?

Re: Node Modules at War: Why CommonJS and ES Modules Can’t Get Along

#113
post #58

Earlier quoted context omitted.

The last time I asked here why async-await is even a thing, when you can just introduce light/green threads, coroutines, you name it, everyone jumped that it is even better when you mark awaiting points explicitly. Now that it goes from a blog post of some popular language designer, seems no one gonna disagree. >async computation mature over the years A good thing, really, but would be much better if the experience f…

In regards to JS, any reasons for a sync await seems to be rationalization. Node is built on V8, which is built for browsers. Browsers have a single threaded execution model that also hides an event loop that runs the entire tab.

Yes, async await is a bug, introduced to workaround the lack of proper concurrency in the runtime.

Re: Node Modules at War: Why CommonJS and ES Modules Can’t Get Along

#114
post #82
post #10

JavaScript just gives to much options. I keep having problems with libraries because ES6 allows import x from "library"; import {x} from "library"; import * as x from "library"; import {x as y} from "library"; Just to compare Java uses this: import java.lang.Double; import java.lang.*; No renaming, not a gazillion options during in- and export, but one statement. If you want to rename something, assign it to a variab…

So what happens when you need to deal with java.time and Joda Time in the same class (e.g. because Joda was part of your public API but you're migrating to Java time). Fully qualified names everywhere, when it would be nicer to have a construct like: import org.joda.time.Instant as JodaInstant; The rest of the weirdness is to make it look like JS destructuring

C# has exactly that FWIW: using foo.lib = libfoo

Re: Node Modules at War: Why CommonJS and ES Modules Can’t Get Along

#115
post #99
post #81

Earlier quoted context omitted.

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%.

Re your point OP also commented/quoted someone with “I don’t think designing a system with the blanket assumption that some feature just won’t get used is a viable path.”

Yes, someone cannot design a system to handle arbitrary libraries with the assumption.

A library author can provide cjs bindings to their library for as long as cjs remains relevant with the assumption that they won't use top level await.

Re: Node Modules at War: Why CommonJS and ES Modules Can’t Get Along

#116
post #76

Earlier quoted context omitted.

It may be the reason, but not the only option. function cpsfoo(cb) {...} function foo() { var thread = this_thread() cpsfoo(x => thread.resume(x)) return thread.yield() } Error and immediate cb invokation handling omitted for clarity. Similar wrapper or wrapper-generator (uncps(f), unpromise(f)) may be done for other primitives.

> Error and immediate cb invokation handling omitted for clarity. ... but this is exactly the reason why callback hell existed. Error handling down the callback branches were a total mess, especially with networked state transfers.

Error handling can be easily added to the example wrapper above, completely hiding all the burden from a user of foo(), who then could do their usual try-catch. It's just my phone keyboard that prevents me from implementing it right here.

Re: Node Modules at War: Why CommonJS and ES Modules Can’t Get Along

#117
post #84

Earlier quoted context omitted.

Isn't "migrating progressively through cross-version codebases" exactly what a 3to2 compiler would allow you to do? You'd write new code (and incrementally port old code) to Python 3, and then when you build the project you'd compile the Python 3 code down to Python 2 before building the entire project as Python 2, including all dependencies. So for over a decade, you'd be writing Python 3 code but building a Python…

> Isn't "migrating progressively through cross-version codebases" exactly what a 3to2 compiler would allow you to do? No. You'd have to migrate everything to Python 3 at once, and then "maintain" two different and incompatible codebases, one generated from the other. > A 3to2 tool would solve exactly the problems you're bringing up, with no intoxication needed! It would half solve (at best) one of them. > I don't see…

> You'd have to migrate everything to Python 3 at once, and then "maintain" two different and incompatible codebases, one generated from the other.

Absolutely not. Well, you could, but the better approach would be to write individual modules in Python 3, and then compile those down to Python 2 at which point they can talk to the existing Python 2 code freely.

> Unless your 3to2 would literally reimplement Python 3 in Python 2

That's exactly what I'm suggesting. Take the existing Python 3 compiler and swap out the backend to generate Python 2 code instead of bytecode.

This is stuff people do every day for other languages. It is very far from rocket science.

Re: Node Modules at War: Why CommonJS and ES Modules Can’t Get Along

#118

Earlier quoted context omitted.

Amen. Babel gets a lot of things right (and arguably has a tougher job than a 3to2 compiler would, given the speed of change and the target breadth / problem surface area).

> arguably has a tougher job than a 3to2 compiler would It doesn't. Not that its job is easy, but its job is to take constructs which are brand new and translate them to an older version of the language. Of the same language. It doesn't have to deal with the language or the APIs literally working differently when used the same way. The Python version of Babel would be 3to3 compiler.

Babel is not limited to JavaScript frontends. You can take any language and write a Babel front-end for it. This is, for example, how Fable compiles F# code to JavaScript. Those two languages are very different from each other -- far more differences than Python 2 and Python 3 -- and it works brilliantly.

Re: Node Modules at War: Why CommonJS and ES Modules Can’t Get Along

#119
post #67

If library authors make esm as a thin wrapper over cjs, won't it hinder tree shaking. And for tools that want end to end esm, like vite. Won't it cause degradation in behaviour?

> If library authors make esm as a thin wrapper over cjs, won't it hinder tree shaking.

Correct. I wouldn't follow the article's advice wrapping ESM with CJS as it leads to larger bundles.

> Won't it cause degradation in behaviour?

For web apps - certainly. The forced sync behavior of CJS wouldn't be very noticeable for local applications however.

Re: Node Modules at War: Why CommonJS and ES Modules Can’t Get Along

#120
post #48

Earlier quoted context omitted.

Sure, but maybe upgrading the existing Python 2 code wasn't the problem: the vast majority of the Python 2 code alive when Python 3 was released was probably scrapped by the time Python 2 was EOL'd . Over a decade is a very long time for a codebase to live. (Again, there are exceptions, but the vast majority of websites or data processing scripts or whatnot are significantly re-written or decommissioned in – pulling…

I made all my Py2 code forward compatible with 2to3. It was mostly a smooth process when you're using the future imports and know what landmines to avoid. It still required manual intervention at times with Unicode support and libraries that have breaking API changes between versions. The end result is something that can be Py3 native whenever I want. 2to3 is the right tool for the job. There is no way to map all Py3…

> There is no way to map all Py3 features back into Py2 so 3to2 would be a broken mess that only supported a subset of the language.

Oh but there is. If you can map them to bytecode, you can map them to Python 2, which is a fully capable language. It won't be a one-to-one map, but that's also not required.

Post reply on HN