TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

ES Modules Are Terrible

77 pointsby kesoralmost 2 years ago

32 comments

alexghralmost 2 years ago
I disagree.<p>What we gained is a native module system that works the same everywhere (Nodejs, browsers, deno, Bun) vs CommonJS which was really only built for Nodejs (with compatibility layers for others).<p>We have a specification for this system and any changes done to it have to follow the same process as any other change done to the language (for better or worse).<p>We have top-level async support that works across import boundaries. This is less useful on the server, but in the browser? With just a `import thing from &quot;<a href="https:&#x2F;&#x2F;example.com&#x2F;foo.js" rel="nofollow noreferrer">https:&#x2F;&#x2F;example.com&#x2F;foo.js</a>&quot;` I get a fully intialised library even if does async requests as part of its initialisation.<p>What we lost is just this<p>``` const someInitializedModule = require(&quot;module-name&quot;)(someOptions); ```<p>The `app.use()` example can be replicated with an async `import()`. Maybe it&#x27;s not as elegant as before.<p>There&#x27;s going to be a lot pain of transitioning a big ecosystem like Javascript&#x27;s to ESM but is that really a reason to not evolve the language?
评论 #36324906 未加载
评论 #36324928 未加载
评论 #36325420 未加载
评论 #36325250 未加载
grosealmost 2 years ago
Counterpoint: Babel and Webpack are the problem.<p>I&#x27;ve long dreaded touching the JS ecosystem but recently I published a package on NPM using ESM + esbuild to bundle it and it was--dare I say--pleasant. Top level await is a killer feature, too. Finally we get a real spec for modules instead of some ad-hoc thing that we twist and turn to get running on browsers.<p>Recently there is a movement in the JS ecosystem to rally around browser APIs, as you can see in edge computing services like Cloudflare Workers and Deno. Modules are a big part of that and one I am quite grateful for. Soon enough Babel will be thought of like Grunt and Gulp and all of the other JS churn.<p>Edit: originally I borrowed the &quot;is terrible&quot; language from the article but honestly I feel kind of bad about that. They&#x27;re both projects worthy of respect, but I don&#x27;t think they should remain as &quot;the status quo&quot;.
评论 #36325560 未加载
mydriasisalmost 2 years ago
Tangentially, I wish Python&#x27;s import and packaging syntax were half as good as anything in JS. Figuring out what combination of adjacent files and directory structures I need to import anything from anywhere is basically cargo cult madness. I am prepared to be proven wrong by 100 commenters, but imo it&#x27;s confusing and sucks. I&#x27;ve had such a great experience with importing and packaging in JS -- to the point when I get something wrong, it&#x27;s because I have Python packaging PTSD and don&#x27;t reach for the simplest solution, where you literally just feed it a relative path and it _does the thing_. That&#x27;s all I want, Python. I want to just give you a path and you do the thing. Instead I have to make a slew of random empty files, install this, move that... why Python, why?
评论 #36330887 未加载
评论 #36331418 未加载
afavouralmost 2 years ago
So much of this is transparently untrue that I’m surprised to see it upvoted this much on HN.<p>&gt; Which then makes people believe that treeshaking is not possible with CommonJS modules. Well, it is - Rollup just chose not to support it.<p>It is possible with CommonJS but it’s enormously brittle and unintuitive. I can write:<p><pre><code> module.exports = { blah: 1 } module.exports.blah = 1 let name = “blah”; module.exports[name] = 1 </code></pre> And countless other possibilities. Then on the other side:<p><pre><code> const { blah } = require(“module”) const blah = require(“module”).blah; const mod = require(“blah”); mod.blah; let key = value ? “blah” : “something else”; mod[blah]; </code></pre> Footguns all over the place that could easily ruin your treeshaking and result in unnecessarily large bundles.<p>&gt; And then people go &quot;well you can statically analyze it better!&quot;, apparently not realizing that ESM doesn&#x27;t actually change any of the JS semantics<p>Also plainly untrue. Similar to the above, I can do:<p><pre><code> let name = “module”; const mod = require(name); </code></pre> With even a slight bit of added complication in that logic static analysis becomes enormously difficult. ESM does not let you do any of that.<p>&gt; loading a full dependency tree over the network would be unreasonably and unavoidably slow<p>Allow me to introduce you to HTTP2. It’s also fast to load dependencies because ESM is statically analysable in a way CommonJS isn’t, so you don’t actually have to evaluate the JS. No, it won’t be as fast as one request but the ability to just write a file and immediately upload it is tremendously liberating, IMO. For small projects Webpack, Vite or whatever is tremendous overkill.<p>&gt; There are no actual advantages to it. At all.<p>Igorance is bliss, I guess.
评论 #36325702 未加载
评论 #36325940 未加载
TheAceOfHeartsalmost 2 years ago
Bait and switch tactics seem really common in the web space.<p>Web components were supposed to make it easier to share components between frameworks. But from what I can tell, this never fully materialized because the tools provided by web components are insufficient and people end up having to import additional libraries. Despite web components being around, most developers continue on with React and friends.<p>With ES modules cascading loads I think there was a lot of handwaving done by claiming you would eventually use HTTP2 to push the full asset graph to the client. Did that ever materialize? What tools support that? Generating this asset graph sure sounds like a build step, and since it&#x27;s possible to have dynamic imports you also have to be prepared to handle those somehow.<p>Adding async support to CommonJS might&#x27;ve been easier than migrating to ES modules. I know that Webpack had support for that at some point, although it wasn&#x27;t widely supported in other ecosystems.<p>A lot of interesting features of the module system are considered out of band and have barely been developed and explored, since it&#x27;s not part of ECMA Script. Module import maps and the like are starting to get supported by browsers. Generating those probably requires a build step too.
评论 #36326104 未加载
评论 #36325654 未加载
评论 #36325258 未加载
laurent123456almost 2 years ago
As of now, I still don&#x27;t know what we got from this switch to ESM. It&#x27;s a terrible breaking change which in some cases make it impossible to upgrade packages, unless you convert you whole codebase first which in many cases is not possible.<p>What&#x27;s the benefit is unclear. Maybe we don&#x27;t need a build step anymore for the browser? But not really - for any project of a significant size, sooner or later a build step will be needed for this or something else. Not to mention that many projects are now done in TypeScript, which means there&#x27;s a build step anyway.<p>For me it sounds like an influential npm developer got this idea that we should avoid a Python 3 situation and decided to force everybody right now to switch to ESM. He maintains enough npm packages to be able to force this and he did. Now we are in this situation where numerous codebases are stuck with certain pre-ESM packages, and there&#x27;s very little we can do about it.
评论 #36324623 未加载
marianoguerraalmost 2 years ago
&gt; And then people go &quot;but you can use ESM in browsers without a build step!&quot;, apparently not realizing that that is an utterly useless feature because loading a full dependency tree over the network would be unreasonably and unavoidably slow - you&#x27;d need as many roundtrips as there are levels of depth in your dependency tree - and so you need some kind of build step anyway, eliminating this entire supposed benefit.<p>Not true, I have developed 3 systems with plain ESMs loading them in the browser with no build step (&gt; 100K lines of code for each project, too many modules to count :)<p>Update: I bundle for release
评论 #36331517 未加载
msoadalmost 2 years ago
I&#x27;ve been following ES module standardization for a while now. From the early days I was not convinced that we need a new syntax. We could adopt require&#x2F;module as language features without breaking the entire ecosystem. It was just not &quot;impactful&quot; and &quot;sexy&quot; enough to do so.<p>Since then I&#x27;m yet to see ES modules solve real problems that CommonJS couldn&#x27;t as the OP argues.
评论 #36389837 未加载
评论 #36327492 未加载
azangrualmost 2 years ago
It&#x27;s python 2 to python 3 transition all over again, only this time it&#x27;s in javascript. Which is most of what the complaints in that gist are — i.e. how much the transitional state that we are in currently sucks.<p>The rest of his complaints are about how `import`s are static, whereas dynamic `import()`s are async; and he doesn&#x27;t like that. To which I say, &quot;meh&quot;.
评论 #36325363 未加载
评论 #36325104 未加载
h1fraalmost 2 years ago
I have nothing against ES modules, actually it&#x27;s a good thing objectively.<p>The problem is how it was introduced to the ecosystem with basically no official support until very recently.<p>First draft in 2009, official release was 2017, a very long time in the Javascript world. Yet, Browsers have minimal support for it; Node.js supported fully in 2020 (node 14, backported to 12); Typescript finally became usable in 2022 (v 4.7); etc.<p>On top of that, some developers arbitrarily pushed this switch to ESM with their very famous lib (eg: sindresorhus) which created a lot of frustration and forks, further more deteriorating the public opinion for ESM.<p>I recently created a new nodejs project in 2023, no personal issue with the modules themselves or the syntax, but still countless of issues with the tooling.
Kiroalmost 2 years ago
Imagine being so full of yourself that you write that last paragraph with a straight face. There&#x27;s obviously no turning back and yet this guy thinks his opinion is so important that it may change the course of things.
joshstrangealmost 2 years ago
&gt; There&#x27;s just no way anymore to directly combine an import statement with some other JS syntax, whether or not the module path is statically specified.<p>I always found this to be an anti-pattern that I tried to avoid, it felt way too “cute”.<p>I won’t pretend the switch to ESM has been completely smooth but it does feel like the better way to pull in dependencies. It reads better IMHO and makes more sense to me.
amadeuspagelalmost 2 years ago
&gt; And then people go &quot;but you can use ESM in browsers without a build step!&quot;, apparently not realizing that that is an utterly useless feature because loading a full dependency tree over the network would be unreasonably and unavoidably slow - you&#x27;d need as many roundtrips as there are levels of depth in your dependency tree - and so you need some kind of build step anyway, eliminating this entire supposed benefit.<p>This is not true if you use a CDN like esm.sh[1] or skypack[2].<p>[1]: <a href="https:&#x2F;&#x2F;esm.sh&#x2F;" rel="nofollow noreferrer">https:&#x2F;&#x2F;esm.sh&#x2F;</a><p>[2]: <a href="https:&#x2F;&#x2F;www.skypack.dev&#x2F;" rel="nofollow noreferrer">https:&#x2F;&#x2F;www.skypack.dev&#x2F;</a>
whoisstanalmost 2 years ago
ES Modules have an unfortunate syntax. I much prefer the function syntax to retrieving a module.<p>&gt;import {URLSearchParams} from &quot;url&quot;; &gt;const {URLSearchParams} = require(&quot;url&quot;);<p>or different destructuring from regular javascript<p>&gt;import {URLSearchParams as P} from &#x27;url&#x27;; &gt;const {P: URLSearchParams} = require(&quot;url&quot;);<p>also you could have used await with require, it would be intuitive for developers as they likely have come across the same syntax before.<p>&gt; const lib = await require(&quot;lib&quot;)<p>I don&#x27;t see any argument why the require approach couldn&#x27;t have been implemented in the browser. What is the actual gain from using ESModules syntax?
评论 #36327719 未加载
math_dandyalmost 2 years ago
Many interesting and fair points in the article. Given perfect hindsight, perhaps the ES Module specification would look quite different today. It might more closely resemble CommonJS and prioritized compatibility with it. But that ship seems to have sailed. The ES module specification has been build into every JS runtime of note.<p>Which of the issues raised in the article are actually actionable at this point?<p>Due to the priorities of the web ecosystem, no breaking changes to ES modules are possible. Can any of the issues raised in the post be addressed in non-breaking fashion?
PurpleRamenalmost 2 years ago
Some months ago, I was building some plugins and other code in Javascript, and to my surprise, my biggest problem back then was to figure out how become code form another file into my working context. There were multiple different code-snippets with different syntax, some worked, others not. This rant explains my problems back then. Getting some up to date documentation for modern javascript seems some kind of gamble at the moment.
hiccuphippoalmost 2 years ago
Why can&#x27;t the engines support both at the same time? One is syntactic sugar over the other.<p>I see libraries providing dist files for both and node refusing to run if you don&#x27;t name your file one way or the other and it seems like a fight over something without distinction.<p>As ridiculous as having to decide if you can only use while loops or for loops. Support both.
bhoustonalmost 2 years ago
I think ES Modules are okay frankly.<p>But the current state of the JS industry where everyone is forced to supporting both ES Modules and CommonJS is hellish. It is the worst of all worlds. It increases testing surface area, slows down build times, adds complexity.<p>I have wasted many days of time on tooling issues related to this and I am a competent developer.<p>At this point we are too far down the ES Modules path, so let&#x27;s just commit to it and get this transition over. CommonJS has lost the argument for all practical purposes a long time ago.<p>Could we please forcibly deprecate CommonJS? Lets please only pick one, no more supporting both because they we do not get the benefits of either.
评论 #36325153 未加载
jrochkind1almost 2 years ago
I don&#x27;t know much about this topic, but I found the OP making an argument that ES Modules are not, as hoped for&#x2F;promissed, <i>better</i> than CommonJS. But it doesn&#x27;t seem to explain any ways they are worse either. The argument seems to be just that we already had CommonJS requires, and it&#x27;s annoying that things are now split with ES Modules additionally.<p>Which could be a legitimate annoyance if they really offer no advantages, I don&#x27;t know. Having two competing systems is definitely worse than having one standard.<p>Am I missing anything, or is this it?
评论 #36325553 未加载
fzeindlalmost 2 years ago
JavaScript should have adopted the exact same package&#x2F;import statements and file structure of Java.<p>It works rather well, it&#x27;s not confusing at all and if you really want something else you can use require etc.
jdauriemmaalmost 2 years ago
Whenever I encounter a really strongly-worded, abrasive opinion like this I look for context. Does anyone know what relationship the author has with the ESM standardization process? Did they offer feedback that was dismissed by TC39? If so, I might be able to empathize with someone who feels that they have been left out or unfairly treated. Otherwise I think the tone distracts from the substance of the article and is also a lousy way to talk about others’ good faith efforts to move JS forward.
okeuro49almost 2 years ago
I learnt JavaScript recently and the CommonJS vs. ES modules issue was very odd to be confronted with.<p>Coming from other languages ES modules seemed much more familiar.
tomashubelbaueralmost 2 years ago
Sometimes I feel like I am the only human on Earth who likes ES Modules end to end, 100 %.<p>Ecosystem divide? What would be the point of ESM if it did not do this? We could have kept using `require`s if the bar is that the new, language-native module system must not cause any sort of a transition period where people adopt it and displaces the previous ad-hoc (IMO anti-) patterns that were used for &quot;modules&quot; before ESM.<p>Doesn&#x27;t work everywhere yet? The support is growing and developers IMO should learn about and default to ESM. That&#x27;s how the support and availability of packages will continue to grow to eventually 99.9 displace previous methods.<p>&gt; And then there&#x27;s Rollup, which apparently requires ESM to be used, at least to get things like treeshaking. Which then makes people believe that treeshaking is not possible with CommonJS modules.<p>I am not convinced the people referred to here are real humans and not made up to support the author&#x27;s argument.<p>Babel&#x27;s problems are Babel&#x27;s problems, ESM is not the cause of the problem here.<p>&gt; ESM in browsers without a build step!&quot;, apparently not realizing that that is an utterly useless feature<p>A hands down amazing feature, something I was pining for for so long and it is finally here. Performance? Sure, if you are building high traffic sites, you will still reach for a bundler, but browser ESM without a build step will allow many intranet and low traffic Internet development teams to ship much nicer code than they do now after buying into bundle-everytime voodoo. If this existed before WebPack, so much spaghetti code could have been avoided.<p>The point of static analysis I can&#x27;t comment on as I have never authored any tools for static analysis of JavaScript codebases using modules, but if I were to, I would be very happy to have an actual language feature for modules with a spec at hand rather than a bunch of IMO ugly patterns that only existed out of necessity because the module system at language level took long to arrive.<p>&gt; CommonJS is so ubiquitous in Javascript-land nowadays that it will never fully go away<p>Unfortunately true, but that doesn&#x27;t mean we shouldn&#x27;t strive for something better. I know the author used the word standard and it can be interpreted many ways, but ESM is IMO better because it is a feature of the language, not the ecosystem.<p>&gt; The vast majority of people who believe they&#x27;re currently using ESM, aren&#x27;t even actually doing so - they&#x27;re feeding their entire codebase through Babel, which deftly converts all of those snazzy import and export statements back into CommonJS syntax.<p>But browsers supporting ESM directly is somehow a problem? It&#x27;s better to rely on bundlers for everything even at the cost of them doing stupid shit like this by default? Not to mention this is completely configurable and avoidable with minimal amount of effort.<p>&gt; the following pattern is simply not possible with ESM<p>That&#x27;s a good riddance from me! ESM being statement keywords and not expression keywords (aside from dynamic imports) is IMO the right choice.<p>&gt; do you want to be able to use ESM-only dependencies<p>Yes, please.<p>&gt; You&#x27;ve destroyed a successful userland specification<p>I am happy to have contributed to proliferation of a successful kernel specification if we&#x27;re sticking with this metaphor.
评论 #36325232 未加载
bmachoalmost 2 years ago
Needs (2021)
jansanalmost 2 years ago
&gt; the only remaining way I see to fix it is to stop trying to make ESM happen<p>I do not understand how this should even remotely be possible. It is a de-facto standard now and used in moste Javascript projects.
评论 #36325493 未加载
azangrualmost 2 years ago
Does anyone know if there are any records remaining about TC39&#x27;s thought process from when they standardized the syntax of the javascript module system?
评论 #36325149 未加载
jonathanedwardsalmost 2 years ago
I thought a benefit of ES module was allowing cyclic dependencies, but I&#x27;m not reading any discussion of that.
tuyiownalmost 2 years ago
The lack of general knowledge in this rant is incredible.<p>Require semantics are bad, and it&#x27;s even worse for a browser. The problem is that the ecosystem is of low quality, and that people bandwagon behind node require compatibility whereas is was a dead end for browsers (no way to implement it with builtin api, processors everywhere became mandatory).<p>Rant author, really, you are the problem. ES module could be a solution.
ravenstinealmost 2 years ago
I really don&#x27;t get the point the author is trying to make.<p>The fact that Babel is often used to transpile ES modules to CommonJS says nothing about whether ES modules are terrible; it mostly speaks to the state of the Node.js community, and perhaps the state of bundling applications for the web. It&#x27;s possible to use pure ES modules <i>today</i> in Node.js, Deno, and in the browser; it just may mean that whatever Node.js package you want to use won&#x27;t make that easy (without something like JSPM.io).<p>As far as lacking advantages over CommonJS, I don&#x27;t know what he&#x27;s talking about either. ESM is much more practical to statically analyze given that it&#x27;s a language feature and not a function that just happens to be in the global scope. If ESM was more of a copy of CommonJS, the author would probably be complaining that it doesn&#x27;t support static analysis or tree shaking.<p>Those aside, the use of the word &quot;terrible&quot; comes across as insincere. ES modules are not complicated. They have their own scope and they can have exports that can be imported elsewhere. If there&#x27;s any other detail or behavior I didn&#x27;t mention, my guess is that it&#x27;s barely important. In my experience, modules work quite well and are an essential language feature. The fact that they have their own scope is particularly nice given that there are many other languages that don&#x27;t give their modules their own scope by default.<p>The author wants import syntax to both support static analysis and call it as a function within any JavaScript expression, yet they provide no example of a hypothetical syntax that would make this possible. Those needs are <i>necessarily</i> in conflict. In other words, the author wants to eat their cake and have it too. As they point out, ESM <i>does</i> provide an import function that can be called this way, but the author is annoyed that it&#x27;s async and may require parentheses (which they believe is a &quot;weird hack&quot; for some reason).<p>Making the `import` function async is a good design choice. In the browser, which is JavaScript&#x27;s natural habitat, importing is necessarily async because other modules have to be fetched as separate files via HTTP. If it weren&#x27;t async, we&#x27;d be stuck bundling &quot;modules&quot; together with Webpack, which goes against what the author actually seems to want, which is actual modules. In runtimes like Deno, being able to asynchronously import from URLs on the backend is pretty nice as well. CommonJS doesn&#x27;t support this without something more akin to a &quot;hack&quot; than the parentheses &quot;hack&quot; the author complains about.<p>Also, there&#x27;s some very foolish comments in that Gist. For one, you can&#x27;t blame ESM because of Typescript. ES doesn&#x27;t give a hoot about Typescript, nor should it. ES modules &quot;[don&#x27;t] work in the browser&quot; because of performance? Nothing is stopping you from bundling parts of your application, ESM or not. It&#x27;s as if http3+ isn&#x27;t a thing either. In fairness, most JavaScript applications rely far too heavily on a bajillion 3rd party packages, and the answer is we should stop doing this as often or to such degrees.
评论 #36325252 未加载
moomoo11almost 2 years ago
Every language sucks there’s always something annoying or confusing or limiting.<p>But does it really matter?<p>I’m solving problems for today that hopefully work tomorrow because who knows what can happen next week. Money could run out and then it doesn’t even matter lol.
lelanthranalmost 2 years ago
Oh god. There&#x27;s so much I disagree with in this article. The most obvious:<p>&gt; And then I end up having to explain to them why, unlike CommonJS, it doesn&#x27;t actually work everywhere yet, and may never do so.<p>Factually and speculatively incorrect.<p>I think all the major JS runtimes support it, and because it is standardised, those that won&#x27;t in the future either probably are not being maintained anyway (and so won&#x27;t be used in the future) or will level-up and add it in.<p>&gt; And then people go &quot;but you can use ESM in browsers without a build step!&quot;, apparently not realizing that that is an utterly useless feature because loading a full dependency tree over the network would be unreasonably and unavoidably slow<p>Not all browser code is a huge mess of spaghetti; sometimes you really just <i>do</i> want to use just one library to make your wordle game (or whatever). Even with a large deptree, CDN&#x27;s and the browser itself can easily help reduce downloads by using cached files.<p>&gt; And then, people go &quot;but now we at least have a standard module system!&quot;, apparently not realizing that CommonJS was literally that,<p>No, it wasn&#x27;t. It was <i>not</i> standardised. It was never something that you could assume was already in your JS implementation. Author also doesn&#x27;t know what the meaning of &quot;literally&quot; is.<p>&gt; And while the initial CommonJS standardization effort succeeded due to none of the competing module systems being in particularly widespread use yet, CommonJS is so ubiquitous in Javascript-land nowadays that it will never fully go away.<p>I doubt it. Non-standard things almost always lose out to the standardised equivalent. The writing is on the wall for any and all ES module equivalents.<p>&gt; The vast majority of people who believe they&#x27;re currently using ESM, aren&#x27;t even actually doing so - they&#x27;re feeding their entire codebase through Babel, which deftly converts all of those snazzy import and export statements back into CommonJS syntax.<p>And? At some point if you want to stop using some non-standardised extra tooling (switch to a babel competitor, for example) then using standardised constructs is much more future proof than directly spitting out CommonJS.<p>&gt; This is a disaster, and the only remaining way I see to fix it is to stop trying to make ESM happen, and deprecate it in favour of some variant of CommonJS modules being absorbed into the spec.<p>I dunno who this guy is; maybe someone important in the JS world? Even if he is, though, this is an awfully arrogant viewpoint. ES modules have <i>already happened</i>, are <i>already supported almost everywhere</i> and <i>works as intended</i>.<p>Just what reason should there be for deprecating it completely? Just because one author is salty that he doesn&#x27;t get to use his favourite library?<p>C&#x27;mon - we all have to move on when our favourite thing goes away. It&#x27;s the way of the world, and having been programing professionally since the mid 90s, I too have had to let go of what I considered fantastic tech in favour of what I considered inferior tech.
its-summertimealmost 2 years ago
&gt; The only way around this is with `await import`, which would break the supposed static analyzer benefits,<p>Isn&#x27;t that the case for commonjs et al for similar situations? And wouldn&#x27;t the solutions for commonjs also apply to ESM?<p>&gt; and even then require weird hacks with parentheses to make it work correctly.<p>Operator&#x2F;et-al precedence is something you&#x27;ll fight regardless, no? Its annoying, yes, but that doesn&#x27;t make it a &quot;hack&quot;, its a oft well understood system.