Hacker News new | past | comments | ask | show | jobs | submit login

Because I don't like breaking things unnecessarily. Some of my libraries are 10 years old and depended upon by similarly old projects that are not using ESM and probably never will.

Besides, it's already going through one transpilation step to go from TS to ESM, so adding a second one for CJS really isn't that much hassle.

I think if node.js had made require() work with ESM, I could probably drop CJS. But since that's probably never going to happen, I'm just going to continue shipping both versions for old projects and not worry about it.




> adding a second one for CJS

Nobody is arguing for that. Once you ship ESM, you can continue shipping ESM.

In Node 22 you can even require() ES modules (with an experimental flag, at the moment)


> > adding a second one for CJS

> Nobody is arguing for that. Once you ship ESM, you can continue shipping ESM.

I'm not sure I follow you there. I did continue shipping ESM.

> In Node 22 you can even require() ES modules (with an experimental flag, at the moment)

Oh, I didn't know about that, cool! Once it becomes un-flagged I might consider dropping CJS.


> I think if node.js had made require() work with ESM, I could probably drop CJS

Why is making downstream have to switch to `await import()` that big of a deal?

You can use async/await in CJS just fine. Sure, sometimes you may need to resort to some ugly async IIFE wrappers because CJS doesn't support top-level await like ESM does, but is that really such a big deal?

Sure, it's a breaking change, but that's what semver major bumps are for.

I just think that if projects want to stay in CJS they should learn how to use async/await. I clearly don't understand why CJS libraries feel a need synchronous require() for everything. (Though to be fair, I've also never intentionally written anything directly in CJS. I learned enough in the AMD days to avoid CJS like a plague.)


> Why is making downstream have to switch to `await import()` that big of a deal?

> You can use async/await in CJS just fine. Sure, sometimes you may need to resort to some ugly async IIFE wrappers because CJS doesn't support top-level await like ESM does, but is that really such a big deal?

It might seem like a small amount of work, but for a library one must to multiply that small amount of work by the number of users who will have to repeat it. It can be a quite large amount in aggregate. And, for what benefit? So I can drop one line from my CI config? It just seems like a huge waste of everyone's time.

Also, as a library user, I would (and occasionally do) get annoyed by seemingly unnecessary work foisted on my by a library author. It makes me consider whether or not I want to actually depend on that library, and sometimes the answer is no.


> multiply that small amount of work by the number of users who will have to repeat it

This is probably where we have the biggest difference in our calculations. I know there's a lot of pain in legacy CJS systems, but from my view (which is maybe more "browser-oriented", which is maybe a bit more Deno/Bun-influences, which comes from a "Typescript-first" mentality going way back to 0.x) it is more legacy "giant balls of mud" maintained by a sparse few developers. I don't see this multiplicand as very big on the scale of library user count. Most CJS for years and years has been transpiled from Typescript or Rollup; most CJS only exists to be eaten by Webpack or other bundler, many of which today rewrite CJS to ESM anyway. From what I see a lot of CJS seems either transpiled out of habit (for some notion of supporting Node < 10 that doesn't make sense with current security support) or by accident (by a misconfigured tsconfig.json, for example, and then often looping back through a transpiler again back to ESM). The way we cut through the Gordian knot of we're all doing too much transpilation to/from CJS is to start eliminating automated transpilation to CJS in the first place. Which is why I find it useful every time to ask people what they are really trying to do when transpiling to .cjs today.

Of course, if your multiplicand is lines-of-code impacted, because I agree there are some great big huge piles of mud in CJS that are likely stuck that way for lack of developers/maintainers and lack of time/budget/money, then worrying about the minority of users still intentionally using CJS is worth caring about, and my sympathies in that situation.

You, of course, know your library's users better than me and maybe you do have a lot of CJS users that I just wouldn't consider in my calculations. I'm not going to stop you from transpiling to CJS if you find that necessary for your library. That's your judgment call. I just wanted to also make sure to ask the questions of "do you really need to?" and "how many users do you actually think it will impact?" out loud. Thanks a lot for the conversation on it, and I'm still going to be a radical banging the "CJS Must Die" drum, but I understand pragmatism and maintenance needs, especially those of legacy applications, and mostly just want to make sure the conversation is an active one and a lot less of passively transpiling stuff that doesn't really need it.


Aight let me chime in here.

I'm a game developer. I make web games. We run our games with a simple nginx server that simply serves the wasm. We have some JavaScript libraries we use. They have to be raw dog .js.

I don't even know what your "ejs" or "cjs" acronyms mean.

We use the discord JavaScript SDK. Discord only ships it as a node module or as .ts.

It's a pain in our ass to update because we don't know what those tools your talking about are and we don't want to know. Just give me the damn .js


I'm on your side. No one should have to care about the difference between ESM (.mjs) and CJS (.cjs). CJS should just be dead and we only need one .js again. If you are following the Discord JS docs and using modern JS syntax `import` and `export` statements (if you are "raw dogging" it, have you heard the good word of <script type="module">?) then none of the above conversation applies to you, congratulations! That's the winning modern JS and you are one of the majority of users using it. The conversation above is about the old dead JS (CJS) and why people are still outputting the old dead JS today when it doesn't matter to people like you or I that just want plain modern .js files (and .ts files and simpler tsconfigs).




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: