[HN Gopher] NPM and NodeJS should do more to make ES Modules eas...
___________________________________________________________________
NPM and NodeJS should do more to make ES Modules easy to use
Author : bcherny
Score : 195 points
Date : 2024-06-20 11:40 UTC (11 hours ago)
(HTM) web link (borischerny.com)
(TXT) w3m dump (borischerny.com)
| ramesh31 wrote:
| >NodeJS can officially drop support for require and
| module.exports in a future version, creating a bit more pressure
| to migrate.
|
| This will never, ever happen. Too much of the foundational
| ecosystem relies on it.
| game_the0ry wrote:
| > This will never, ever happen.
|
| I hope for the sake of the nodjs ecosystem, you are wrong.
|
| Fragmentation issues are one of the many reasons that nodejs
| struggle with adoption.
| baq wrote:
| > nodejs struggle with adoption
|
| Woah there. If nodejs is struggling for adoption I don't know
| what isn't.
| game_the0ry wrote:
| Let e put it differently: nodejs would have _more_ adoption
| if it had less perceived instability.
| bastawhiz wrote:
| If it does happen, it'll only cause more fragmentation.
| Because lots of projects and libraries simply won't upgrade.
| Look at Python: it took them _decades_ to get folks to
| upgrade to py3k because they broke the old code. Do it to
| Node and it 'll be decades of fragmentation.
| dgb23 wrote:
| Breaking code that doesn't need to be broken is the biggest
| redflag for a platform or foundational library.
| jeswin wrote:
| > Too much of the foundational ecosystem relies on it.
|
| Not saying it needs to be done, but this can possibly be
| handled via a tranpiler layer. It might make CommonJS a bit
| slower to startup (but fully functional), which is an added
| incentive to move.
|
| Again, I don't have any opinion on whether this is a good
| thing. Like you said, too many modules depend on it.
| mistercow wrote:
| You don't really even need a transpiler. Require is basically
| just a function which loads a file, wraps it in some
| boilerplate, and evals it. You could just rip that runtime
| code out of node and provide it as a compatibility library.
| bastawhiz wrote:
| > but this can possibly be handled via a tranpiler layer. It
| might make CommonJS a bit slower to startup (but fully
| functional), which is an added incentive to move.
|
| "The new version runs your old code slower and it's enough to
| notice" would be a death blow to the ecosystem. No major
| company is going to upgrade to that. It's already a project
| to drag a major codebase kicking and screaming to a new LTS
| release of your runtime (even if it makes code faster), do
| you really think folks will invest the time to work to make
| their code run slower unless they invest even more effort and
| modify ~every module in their codebase?
|
| ESM isn't implicitly good. The benefits of ESM are almost
| entirely theoretical for pretty much everyone who is content
| with CJS. I manage codebases right now that total half a
| million lines of typescript and js and I think I simply
| wouldn't notice any improvements from converting any of the
| code. The point being: this isn't a problem for me or people
| in similar situations, it's a problem for the folks working
| on Node and the standards. Forcing folks to upgrade or making
| their code worse to exert any kind of pressure _does nothing_
| to help anyone.
| tqwhite wrote:
| An insanely bad idea.
| Aeolun wrote:
| Or you can use Bun and have it handle all the nonsense. Or
| esbuild, but then you get a big blob, which isn't really usable
| for a lot of things.
|
| The extensions were always silly to me. Who changes only a few
| files to esmodules? You either change your whole project or not
| at all.
| jasfi wrote:
| I look forward to the day when Bun can run Next.js. Apparently
| the main showstopper is in the Next.js router.
| evilduck wrote:
| I'm not steeped in the history of this issue but I
| periodically run a maintained and up to date NextJS app via
| Bun in a dev env just to monitor performance and
| compatibility. It uses the app router and the edge runtime
| middleware, hosted from a Docker container. I haven't seen
| massive benefits using Bun since Next doesn't use the Bun-
| specific libraries that make their performance numbers great,
| but I haven't seen any game breaking issues either, it runs
| and all the app's E2Es pass.
| afavour wrote:
| > Who changes only a few files to esmodules? You either change
| your whole project or not at all.
|
| Transition. It's a much lighter lift to transform a project
| piece by piece than do the whole thing.
| lefrenchy wrote:
| Does it actually handle it though? I use bun to run my remix
| app at work and I have run into ESM/CJS issues.
| dimgl wrote:
| Bun handles all of the nonsense but the catch is that it blows
| up both in dev and in production. Wake me up when Bun doesn't
| segfault/fail to work at all.
| knallfrosch wrote:
| I don't know which is which. I don't care. I don't understand the
| benefit of a top-level await if I can simply await in a different
| file. I use Typescript which adds a layer in-between anyway. At
| work, we use Angular, which (I think) uses both Typescript and
| maybe esbuild. Or Webpack. Does it compile to ESM, or CJS? Who
| knows, and it will change in 2 years again anyway.
|
| All of that is something that I consider to be platform-level.
| It's insane that millions of feature-writing devs are expected to
| know all these arcana.
|
| Then again, it might be fixed(tm) soon r
|
| https://joyeecheung.github.io/blog/2024/03/18/require-esm-in...
| dboreham wrote:
| Now we see the benefit of having adults in charge, e.g. as is
| the case with golang for example.
| throwitaway1123 wrote:
| Go has the benefit of not having to reach a distributed
| consensus amongst a variety of individual browser vendors.
| Try compiling a large Go project with tinygo to get a glimpse
| of what it's like to have to deal with multiple independent
| runtimes [1]. If the browser vendors had been able to ship
| ES4 or ES5 with module support between 1999 and 2009, then
| Node probably would have implemented it from the very
| beginning, and there would be no dichotomy between CJS and
| ESM.
|
| [1] https://github.com/evanw/esbuild/issues/1111
| dimgl wrote:
| The whole point of this is that ESM was very poorly handled.
| It's irrelevant to TypeScript, esbuild, Webpack, etc. That
| tooling handles the complexity for you and sometimes that
| backfires. I've run into a lot of headaches with the TypeScript
| compiler.
|
| The fact that you don't know whether your codebase uses
| TypeScript, esbuild or Webpack is disappointing. It means that
| those worries have been handled for you and you don't care to
| learn them, which is never a good stance if you work with this
| on a daily basis. But I somewhat agree that it should all be
| vastly simpler.
|
| I also kind of agree with the downvoted/flagged comment re:
| Golang. The way the JavaScript ecosystem works is highly
| dependent on the way Node is handled. And Node has, for many
| years, made ESM needlessly complicated.
| knallfrosch wrote:
| > The fact that you don't know whether your codebase uses
| TypeScript, esbuild or Webpack is disappointing. It means
| that those worries have been handled for you and you don't
| care to learn them
|
| En contraire. The problem is that some years ago I did learn
| the basics, but the ground has shifted underneath my feet
| multiple times. There's not really an incentive to learn the
| finer points of ESM-vs-CJS if Typescript hides the input into
| the system, Angular has its own ideas about modules, uses
| Webpack or babel internally and then spits out CJS anyway.
|
| The whole JS ecosystem is nice if you edit 10 files by hand,
| but I just don't know what I should do with the knowledge
| that I should "require cjs" when I need Typescript for type
| safety and it'll only let me "import ts" anyway.
| Shacklz wrote:
| > All of that is something that I consider to be platform-level
|
| I agree with this, but the whole point of the blog-post is that
| the "platform" currently handles this rather poorly.
|
| I have yet to see a frontend-project that was bigger than some
| three-person-garage-hobby that didn't occasionally run into CJS
| versus ESM issues. Maybe not something that pops up on the
| radar of all the devs in the project but at least at the level
| of folks who take care of the setup and whatnot, it often pops
| up in rather painful fashion. Case in point; a few angular-
| versions back, umd-bundles were dropped, which at least for the
| project I worked on caused me quite a lot of headache as some
| of our tool-chain (most notably our testing-setup) relied on
| angular shipping commonJS-compatible modules.
|
| It's currently also a major pain for anyone publishing an npm-
| package, even if it's primarily intended to be run on node. The
| kind of incantations one has to do are just insane (especially
| if you dared to import from node:crypto or want to support more
| than just the latest lts); I've just stopped bothering after
| tearing my hair out for a weekend to no avail, even though I
| really wanted to support ESM as well.
| rezokun wrote:
| Or JS ecosystem should drop ES modules since they have only
| brought pain and unnecessary complexity without real benefits for
| years.
| pavlov wrote:
| ES modules work natively in browsers, which are the slow-moving
| ships of the ecosystem. Changing course for them is completely
| unrealistic.
|
| There's a billion browser clients out there. That ensures that
| whatever API they ship, an increasing amount of code will be
| written directly against it. Everybody else just needs to adapt
| or be seen as incompatible with the baseline of JavaScript.
| rezokun wrote:
| Show me a real product on the web that does not compile or
| bundle and uses native modules for code delivery. It's a dead
| technology that only fragments the ecosystem and makes life
| harder.
| jsmith99 wrote:
| Many bundlers output module format - it makes features like
| code splitting (chunking into separate files) convenient.
| rezokun wrote:
| ES modules mean you don't need to bundle your code; you
| just include your index.js in HTML, and all 30,000 JS
| files of your project come to the user's browser without
| trouble or delay (let's wish them luck, lol). Since
| you're bundling, it doesn't matter which module type you
| use; CJS has worked with code splitting perfectly for
| over 10 years. However, it's a pain every time you try to
| import a CJS library in your ESM or vice versa. The truth
| is, you can't just drop all legacy CJS packages in most
| real-world projects.
| pavlov wrote:
| _> "all 30,000 JS files of your project come to the user
| 's browser without trouble or delay (let's wish them
| luck, lol)"_
|
| If only there was something in the HTTP protocol to make
| it more efficient to load multiple requests from the same
| server. Alas that must be a pipe dream, and every little
| image and script is loaded separately.
|
| Oh wait, it's not 1996 anymore...?
| tracker1 wrote:
| I hear there's this new HTTP 2 spec that might be able to
| do something like that... but obviously we need to wait
| on browser support
|
| /s
| pavlov wrote:
| The web is not just for "real products". It's also a
| platform with tens of millions of hobbyists and dabblers
| writing HTML and JavaScript.
|
| I promise you they will use any feature that's documented
| on MDN as being available in all browsers. And ES modules
| do make life easier for someone who's just writing HTML and
| JS and doesn't know anything about build tools.
|
| IMO, it's the wrong attitude that we should focus on the
| professional ecosystem and forget about this use case.
| Probably most people writing front-end code got their start
| by creating a HTML file in Notepad (or equivalent) and
| loading it via file:// into the browser.
| WorldMaker wrote:
| It's a _great_ development experience today: no waiting for
| bundlers, easy inner dev loop, let the Browser do all the
| loading just like Web 1.0 and JS development was maybe
| supposed to feel.
|
| It will become more common in products. There are going to
| be startups that see that great development experience and
| long for some returns towards "just FTP it to the web
| server as-is" CI/CD processes. There are going to be more
| product owners everywhere (startups, Enterprise) that think
| that HTTP/2+ adoption (or even HTTP/1.1 properly
| configured) is acceptable in the real world and that they
| are done with most of the needs for bundling.
| jeswin wrote:
| IMO, it's the best thing to happen to Node. It (kinda) unifies
| browser and server syntax, and across competing server-side JS
| frameworks (Node, Deno, Bun). CommonJS was clearly a NodeJS
| thing.
|
| We embraced ESM a couple of years back. It was a bit harder
| earlier on; for example our test frameworks didn't support
| mocking ESM code well enough. But now there's hardly anything
| to complain about. There's no going back really - we wouldn't
| want to.
| 123yawaworht456 wrote:
| >IMO, it's the best thing to happen to Node. It (kinda)
| unifies browser and server syntax, and across competing
| server-side JS frameworks (Node, Deno, Bun). CommonJS was
| clearly a NodeJS thing.
|
| what the fuck was the point of unifying this particular thing
| at such a great PITA cost, when obviously none of node APIs
| work in the browser?
|
| should things like Buffer be removed too? the browser only
| has Uint8Array, after all.
| afavour wrote:
| Couldn't disagree more. It's wonderful having the same module
| syntax on server and client.
| game_the0ry wrote:
| Huh? You need to elaborate a bit before making a statement like
| that, friend.
| mirekrusin wrote:
| And yet approximately 100% of js/ts devs are using ES module
| syntax and don't write blog posts about it. Magic.
| tqwhite wrote:
| According to the article, three quarters of the npm projects do
| not use ESM. Their programmers must be very magical.
| catapart wrote:
| Just use JSR[0] and only deal with npm when a project forces you
| to do things backwards. Since JSR packages are available on npm,
| there's nothing lost.
|
| [0]https://jsr.io/
| creesch wrote:
| Neat to get to know JSR, but doesn't this have very little to
| do with the contents of the article you responding to? While I
| know NPM is in the title, the actually article is about module
| imports which JSR doesn't change.
| catapart wrote:
| The article is saying "this ecosystem should change because
| it doesn't do specific things that make sense for it to do".
|
| JSR says "here's a way to leave the original ecosystem alone,
| but have a better-fitting ecosystem that does the things you
| want". (not sure about the 'jsr doesn't change' bit? It
| literally requires ES modules, in lieu of common js modules).
|
| Seems pretty relevant, to me, but YMMV. I understand it's not
| a direct answer, but it seems as relevant as "here's
| typescript" to someone saying "we should add types to
| javascript".
| jmondi wrote:
| I have mixed feelings about the JSR requirement for explicit
| typing. Other than that, it is pretty great!
| catapart wrote:
| Hm? This is news to me. As far as I know, you can just
| publish pure javascript. I know that it's going to give you a
| worse 'score' if you don't have types, and it may require
| explicit typing of TS (but, strictly, so does TS), but I
| wasn't aware that there was not any way to publish to JSR
| without types. I'll have to look in to that, thanks!
| nox101 wrote:
| jsr seems great! I hope they work out their kinks but I'm
| really glad someone is trying to push things forward.
| can3p wrote:
| I think the module imports apis are a python2/3 moment for
| node.js ecosystem. There is no clearly superior way and as a
| consequence not too many people care, however it hurts for real.
|
| The proposal to disable node.js style imports will just split
| ecosystem and make a large part of industry stick to ancient
| version / make a fork. Is that really worth the gain? Just check
| how long it took some bigger projects to migrate from python2 to
| python3
| cxr wrote:
| The difference is the language/standard in question neither
| originated with NodeJS nor is NodeJS now nor has it ever been
| led by the people behind the language/standard (unlike
| Python)...
|
| When you hear "NodeJS", you really need to bethinking of it in
| the same category as IE (wrt browser behavior) or Visual C/C++.
| It's but one, often (knowingly/deliberately) quirky, non-
| standard implementation by a group that doesn't necessarily
| have your best interests at heart or the interests of those
| outside their own platform umbrella.
| pcloadletter_ wrote:
| How are the deer in Nara?
| bcherny wrote:
| Cute, when they aren't trying to eat my phone.
| gbuk2013 wrote:
| Can someone explain to me what the advantages of ESM actually are
| to me as a backend dev who uses import / export syntax in TS
| already?
|
| Parent article mentions static analysis and synchronous loading
| on startup but that has never been an issue for me despite
| building some large and complex Node apps over the years.
|
| I've looked into this in the past but all I could find are strong
| opinions without solid technical reasoning.
| afavour wrote:
| IMO the game changer in your scenario is when type annotations
| are added as a standard JS feature:
|
| https://github.com/tc39/proposal-type-annotations
|
| At that point (and with ES modules) you'd be able to run your
| TS code directly without any transpilation necessary. I'd
| _love_ to remove all the build process junk from my projects
| and have them run quicker.
|
| I've written a few projects as plain ESM JS with JSDoc type
| annotations and it truly is a joy to bypass build steps. JSDoc
| type annotations do get annoying as a project grows to a
| certain size, though.
| gbuk2013 wrote:
| When I see "stage 1" and "if they stick within a certain
| reasonably large subset of the language" the cynical old dev
| in me starts waving a YAGNI sign. :)
| afavour wrote:
| Honestly as you read through the proposal the immediate
| impression is "they're just describing TypeScript syntax",
| which is... fine, I think? But I do feel like it would be a
| considerably quicker process for Node to just add the
| ability to parse a TS file than it will be to go through
| this formal approval process.
| eyelidlessness wrote:
| The process is standardizing the ECMAScript language. It
| would make types (as comments) standard for all JS
| runtimes, not just Node. I don't think the community at
| large wants _more non-standard Node stuff_ , as that's a
| frequent point of pain and complaint (see OP article as
| an example).
| wokwokwok wrote:
| > The aim of this proposal is to enable developers to run
| programs written in TypeScript, Flow, and other static typing
| supersets of JavaScript without any need for transpilation,
|
| > if they stick within a certain reasonably large subset of
| the language. <-------- !!!!!!!!!!
|
| js + type annotations !== typescript
|
| The most recent discussion sums this up with, I think _this_
| comment:
|
| > EAO: Okay. So the sense I get overall of this whole
| proposal, that it's more of a - it's a solution looking for a
| problem that it's trying to solve a year ago when this got
| accepted for Stage 1, the problem statement that was in fact
| considered then was only effective we made up or made
| concrete during the meeting itself, and then - so what it
| looks like now is that since then, that problem statement has
| evolved to this current form of unifying or unforking
| JavaScript and somehow then presenting type annotations as a
| way of achieving this result. However, I've not been able to
| find any conversation anywhere or description of how in
| practice this unification is supposed to happen as a
| consequence of accepting type annotations.
|
| No one had a good answer to that, because there isn't one.
|
| Anyhow, tldr; this has basically nothing to do with any
| tangible reason to think ESM is good or useful in anything
| other than a massively broad, speculative 'maybe in the
| future' kind of way.
|
| ...it is most certainly not any kind of advantage or reason
| to use ESM for anyone, right now.
| afiori wrote:
| Being able to copy paste typescript snippets in the browser
| console is enough of a benefit in my opinion
| WorldMaker wrote:
| > js + type annotations !== typescript
|
| It's _very_ close though. The proposal is well written and
| covers the cases where existing Typescript code would not
| parse correctly /work as intended under the proposal. Most
| of those cases are pre-1.0 Typescript features still in the
| language for backwards compatibility but generally frowned
| upon and that you probably already have strict warnings and
| linter errors preventing you from using today. The big
| exception is a lot of TS codebases heavily use `enum` and
| I've still not seen enough suggestions to tighten the
| linter warning against it. (But there are at least some of
| us suggesting avoiding TS `enum` today.)
| rty32 wrote:
| I would argue the benefit is just making everything much
| simpler. You never need to think about module systems and
| interoperability -- there is only one module system to deal
| with.
|
| That proposal seems to have stalled, and I doubt it's going
| anywhere. Here is the thing: people want hard, strict
| compiler checks that can be enforced at all time, not Python-
| style type hints. If you want JavaScript but type checked,
| Typescript is the de-facto standard. Either do "checkJS" or
| convert the project to Typescript. In fact, the latter is
| much better in terms of expressiveness.
| tqwhite wrote:
| It only makes it simpler if you have a new project and can
| be ESM pure. If you are working with existing code or need
| non-ESM modules, everything is _much_ more complicated.
| an1sotropy wrote:
| Fwiw the github page for that proposal isn't linking to what
| seems to be the most recent discussion *. I thought type-
| annotations-as-comments was a no-brainer, but it seems messy.
| The Sept 2023 discussion shows that it is complicated by the
| current variety of annotation schemes (TypeScript is not the
| only one), and the parsing subtleties, which gave rise to
| unresolved questions about what is the basic motivation.
| bummer.
|
| * https://github.com/tc39/notes/blob/main/meetings/2023-09/se
| p...
| Quothling wrote:
| There isn't that much difference on the backend if you use Node
| and Typescript. ESM is the standard for JavaScript and you'll
| probably run into situations where you can't use a new
| JavaScript feature with CommonJS as early as you can with ESM.
| There are disadvantages and advantages to how the modules load
| on Node, but ESM is generally improving faster than CommonJS.
|
| If you're looking into other runtimes ESM used to be the way to
| go because of Deno, but these days you're likely either running
| Node or Bun and both work well with CommonJS and ESM.
|
| If you do both frontend and backend work, or if your team has a
| lot of cross-over between the two sides of the ecosystem, then
| it'll likely be easier for you to use ESM on both ends as
| CommonJS isn't supported by browsers.
|
| I think the primary reason CommonJS is still around is mostly
| because Typescript replaces it's import/export module system
| with something that's basically similar in syntax to the way
| ESM does it untill it gets transpiled into Javascript. If
| people actually had to work with CommonJS modules in 2024 then
| I think they'd likely go insane.
|
| Not everyone will agree with me on this, but I don't think
| there is a reason to rewrite old projects into ESM unless you
| have a very good reason to do so. That being said, there isn't
| really a good reason to start new projects with CommonJS
| either... Unless you have a really good reason to do so.
| WorldMaker wrote:
| A big technical reason especially specific to using Typescript:
| not transpiling to CJS speeds up your Typescript builds.
|
| It also opens up more options when Typescript is just "type
| stripped" rather than transpiled to an incompatible module
| syntax. You probably still want a full Typescript compile at CI
| time to get robust typechecking, and you'll have the Typescript
| LSP doing its thing in your IDE still, but you can use type-
| stripping tools like esbuild for very fast type stripping in
| some portions of your inner dev loop.
|
| The static analysis that ESM supports is handy because it opens
| up technical benefits like Tree Shaking. Your apps might run on
| SSDs, you probably don't have a lot of reasons to bundle them,
| you likely aren't worried about on disk size, you might not be
| worried about bundle publish size to npm, and so you might not
| think Tree Shaking applies to you, but V8 under the hood of
| Node is still going to do Tree Shaking of _memory_ and garbage
| collection for you with ESM in ways that it simply cannot with
| CJS. I 've seen some real memory performance gains in Node apps
| just switching from CJS to ESM already, and V8's ESM
| optimizations only seem to get better as more ESM is deployed
| in the wild.
|
| There are more, smaller technical benefits, but "type stripping
| not transpiling" and "in memory tree shaking" are strong ones
| that are easy to overlook.
| paulddraper wrote:
| > Can someone explain to me what the advantages of ESM actually
| are to me as a backend dev who uses import / export syntax in
| TS already?
|
| 1. The downstream users of your backend library can use ESM JS.
|
| 2. You can author (or output) isomorphic code that works in
| Node.js and other environments.
|
| 3. Static analysis tools can more reliably understand your
| dependency graph, e.g. find unnecessary code/modules/packages.
|
| 4. You can use a custom load API to do customized operations.
| E.g. import a YAML file as a JavaScript object.
|
| If none of these apply to you individually, then you don't have
| a lot to be gained.
| bastawhiz wrote:
| The simplest solution is to stop requiring the top level package
| to be a module. Allow es modules to be require()-ed. It's be
| synchronous and slow and ideologically impure, but it'll make it
| so that millions of projects (mostly private!) will be able to
| start adopting es modules without a massive refactor. Anyone with
| a project of significant age or size looks at ES modules now and
| thinks "fuck it". There's no return on investment to convert
| (other than less pain while trying to upgrade or adopt new
| libraries). It's a big undertaking with loads of risk (modifying
| import order isn't safe!) and the payoff is "it's the shiny new
| thing".
|
| I had been using adminjs at work. Their new major version was
| ESM-only, and it was easier to _write a new admin panel from
| scratch_ than it was to refactor our entire codebase to be ESM
| just so we could upgrade one library. I expect that's the
| situation at hundreds of thousands of other companies.
|
| Like for all the belly aching that happened over async functions
| (and the whole function color rant), synchronous and asynchronous
| functions work together just fine through plain old promises. You
| can easily use async functions alongside functions that use old
| fashioned callbacks. ESM vs CJS is a file coloring (versus
| function coloring) problem, but there's no interoperability.
| There's no escape hatch when you just need one file to use
| another file but their colors are incompatible.
| throwAGIway wrote:
| What about the createRequire function?
| bastawhiz wrote:
| Why should I need to go out of my way to do this? Why do I
| need to care what kind of module I'm importing and reach into
| the stdlib to run code? It should just work.
| throwAGIway wrote:
| To be frank I don't care about these questions, perhaps
| you're right and it should, but whatever. It's a solution I
| used in the three cases it was necessary that blocked
| moving my codebase to ESM.
| sureIy wrote:
| You're missing the point. Of course createRequire is a
| solution, it's always been. The problem are tools and
| sub-dependencies that you can't touch.
| afavour wrote:
| > it was easier to _write a new admin panel from scratch_ than
| it was to refactor our entire codebase to be ESM just so we
| could upgrade one library
|
| A middle ground answer would be using import() in CJS to
| asynchronously require the ESM module. It would require some
| hacking around your loading flow to ensure the module loads
| before you try to do anything with it but would still be
| preferable to rebuilding the entire thing.
| bastawhiz wrote:
| I don't disagree! But is there really an argument (other than
| an ideological one) for why it needs to be an awaited import?
| Why does it matter that it's async?
| eyelidlessness wrote:
| ESM (as standardized, not necessarily as implemented in
| Node) treats import specifiers as URLs. That alone would
| inherently be async because network requests are async
| across basically all JS runtimes. ESM was also later
| extended to support top level await, making module
| execution itself async.
|
| Node has recently taken a more pragmatic approach, by
| treating local specifiers as potentially synchronous,
| allowing sync require() of ESM... which then fails _if_ the
| required module uses top level await.
| WorldMaker wrote:
| "Sometimes works, but can also blow up at runtime after
| any upgrade" seems to me like a "pragmatic cure" that is
| worse than the existing "disease" of needing to treat all
| ESM imports as async and/or migrating all uses of
| `require()` to `await import()`. If incrementally moving
| a CJS code base to use `await import()` in more places is
| too hard then you probably have other problems you've
| overlooked for too long (bad promise usage, callback
| waterfalls, etc).
|
| (But I'm a hardline "all you need is type=module" sort
| and think a CJS=>TS emitting ESM "rip off the bandaid"
| approach to CJS legacy libraries works and is
| fundamentally easier than most of the "pragmatic"
| solutions to CJS/ESM interop. It is past time to jettison
| CJS out the airlock.)
| zarzavat wrote:
| Fetching code at runtime over the network makes sense in
| a browser, it doesn't make sense outside of a browser and
| would actually be a huge security risk without all of the
| security features that browsers have. So it just
| reinforces the perception that ESM was only designed for
| browsers.
|
| Both TC39 and node utterly cocked this up. The design of
| ESM is bad, async imports are a stupid idea, and node's
| implementation has been beset by ideology.
| tqwhite wrote:
| I'd say it's exactly the opposite. Neither require() or
| import require an async code structure. The biggest reason
| I avoid ESM like a plague is that many of my projects are
| not, and do not need to be, async. Adding import() is a
| huge hassle because it is async.
|
| Adding an importSync() function would be a perfect
| solution.
| sureIy wrote:
| importSync exists and it's called import statement.
| tqwhite wrote:
| That's a pretty douchey thing to say.
| IggleSniggle wrote:
| That was my first thought, and what I attempted first in my
| project. But it turned out that rewriting everything, while
| being incredibly tedious, was significantly easier to reason
| about and ensure continuity than developing my own bespoke
| dependency loader in a large project where not all portions
| are well understood.
| ComputerGuru wrote:
| I have a custom loader that can operate in both sync and
| async mode with the same syntax; it started off as a single
| loader to load AMD and CommonJS but I've been meaning to add
| ESM support as well (it was more opaque than I liked when I
| last tried, required too much browser magic).
|
| https://github.com/mqudsi/loader
| microflash wrote:
| > Allow es modules to be require()-ed. It's be synchronous and
| slow and ideologically impure, but it'll make it so that
| millions of projects (mostly private!) will be able to start
| adopting es modules without a massive refactor.
|
| This is already available in Node.js 22 [1] with `
| --experimental-require-module` flag.
|
| [1]: https://nodejs.org/en/blog/announcements/v22-release-
| announc...
| jauntywundrkind wrote:
| Before Node had any/experimental module support (April 2019,
| https://nodejs.medium.com/announcing-a-new-experimental-
| modu...), I'd been using std-things/esm loader for Node.js,
| which seemed to have no problem allowing CJS and ESM to
| interop, require and import each other. In my experience it
| worked flawlessly. https://github.com/standard-things/esm
|
| It's wild to think about: esm has taken nearly a decade to be
| feasible for folks to use, without heavy encumbrance; it was
| the key feature of es-2015/es6!
|
| It took many more years for import-maps to become a thing,
| such that we could start using modules in a modular fashion;
| we've had to use bundlers/codemods to re-resplve
| dependencies, unless you've been going to go Deno's original
| path of just hitting absolute urls wherever they be. There's
| still no standing proposal for how we get import-maps on
| service-workers & shared workers; modules still are not a
| ubiquitous feature of the core web & JavaScript ecosystems. 9
| years latter. https://github.com/WICG/import-maps/issues/2
|
| It's been hard being a webdevs, when the future remains so
| partially implemented.
|
| The article's exploration of the bomb ecosystem is telling.
| And is much of the reason I hope JavaScript Registry (jsr)
| project might succeed. Npm will never escape it's past. CJS
| is going to be in there for a long time. Being on a registry
| where everything is esm & typescript, that sounds divine.
| https://deno.com/blog/jsr-is-not-another-package-manager
| z3t4 wrote:
| Did anyone actually want ES modules, and are anyone using
| ES modules in production today? I don't think so except for
| transpiling languages that compile and bundle the JS. The
| only argument against lazy loading is that single threaded
| UI's will freeze for a few ms when the code loads, but if
| you compare that to the time it takes to fully load a
| modern website that point is moot.
| apitman wrote:
| There are a few hiccups, but I've found ESM to be a huge
| win overall. The killer feature for me is the ability to
| write code that can be imported in a browser without any
| sort of build step. You don't even need node/npm. Just
| download the file/directory from somewhere and import.
| It's perfectly feasible to build a complex browser app
| with many dependencies using nothing but git submodules.
|
| The main thing you're missing out on is the optimizations
| that come with bundlers. But they should be treated as
| just that: optimizations. You shouldn't be required to
| use a bundler just to develop/distribute JS programs.
| jauntywundrkind wrote:
| (Most) everyone was already using bundlers at this point.
| Tree shaking was much easier to do after the dependency
| graph became computeable. Which it wasn't with CJS;
| require could happen anywhere with any parameters. And
| require happening anywhere while being sync was kind of a
| non-starter. That freeze is amplified by most projects
| having hundreds of not thousands of requires across it's
| dependency graph.
|
| There's definitely some truth to your gripes. Back in
| 2015 there was a ton of latent hope http/2 push and ESM
| would let us get away from bundling & perhaps even
| needing build steps at all. That hasn't panned out.
|
| Indeed, push was removed entirely!
| https://groups.google.com/a/chromium.org/g/blink-
| dev/c/K3rYL... Except it's still the core backend for
| Push API. Alas, fetch, in spite of many years of asking
| for it, never got the ability to observe a Push request,
| so devs literally never had a chance to explore the
| possible content update/content discovery use cases that
| make so so much sense in Web Push Protocol. Crying waste
| & shame; Push had promise outside of asset delivery but
| it never got a chance (except the deeply browser-
| intermediated Push API).
|
| There are a variety of tools & options for bundlers to
| emit bundled esm. Which would nicely make your bundle
| usable by multiple different consumers.
| apatheticonion wrote:
| Bundler developer here: some bundlers (like Parcel) use
| esm imports within their generated runtime output to
| facilitate loading dynamic bundles.
|
| It's a bit simpler (and I'd assume faster) than the
| traditional approach of dynamically creating a script tag
| at runtime.
|
| Additional features like access to import.meta lets you
| get the path to the current script which also helps
| bundlers with resolving the paths to dynamic imports
| without requiring the developer to specify the base path
| explicitly.
|
| There are problems though, for example you cannot retry
| an import() if the internet drops. The failed import is
| cached so the browser will fail the import again on
| retry, even if the connection is restored
| https://github.com/fatso83/retry-dynamic-import
| tqwhite wrote:
| EXACTLY!!!
|
| (Though I'd be happier with importSync() to identify the use
| of ESM packages.)
| paulddraper wrote:
| Implementing it in require() allows a library to migrate
| from CJS to ESM, without breaking any of its downstream
| users.
| alexose wrote:
| That's awesome! I can't wait to try this.
|
| Maybe I'm in the minority, but using NPM packages that have
| changed over to modules continue to be one of my biggest
| annoyances in NodeJS: npm install node-fetch
| const fetch = require('node-fetch'); Error
| [ERR_REQUIRE_ESM]: require() of ES Module npm
| install node-fetch@2
| throwitaway1123 wrote:
| You might just be using the node-fetch example as a stand-
| in to make your point about esm/cjs, but the fetch api is
| built in to Node (since v16.15) and is no longer even
| considered experimental as of Node 21+.
|
| https://nodejs.org/docs/latest-v22.x/api/globals.html#fetch
| tyleo wrote:
| By god do I agree with this. I feel like all my most diabolical
| ESM issues are beating the tsconfig.json, webpack.js, and
| package.json into shape to get ESM and legacy working.
| TheRealPomax wrote:
| Although on a payoff note, it's not even the shiny new thing,
| it's almost a decade old. We really need a Python 2.7 style
| "no: we're done with this. Don't uplift your code as much as
| you deem necessary, but we're moving on. You've had a decade by
| now" event for Node.
| hn_throwaway_99 wrote:
| The whole thing feels like IPv6 adoption to me: Make v2 of a
| thing that is undeniably better, but downplay/ignore the
| migration strategy and then just complain that people are lazy
| if they haven't migrated yet.
| cxr wrote:
| > There's no return on investment to convert
|
| Nothing except doing things the standard way so that standards-
| compliant language implementations (and other tools) can work
| with them instead of targetting IE^H^H NodeJS's non-standard
| quirks.
|
| > the payoff is "it's the shiny new thing"
|
| NodeJS's reality distortion field has claimed another.
|
| Ecmascript modules are going on 10 years old at this point.
| (For comparison, that's more than the amount of time that
| NodeJS existed when modules weren't a part of the language.)
| akira2501 wrote:
| > It's be synchronous and slow and ideologically impure
|
| Sure. It also "just works" at the CLI. Sometimes I just want to
| test code quickly at the CLI. I'm not into "architecting" this
| part of my code as much as ES thinks I want to.
| jeswin wrote:
| ES Modules are better in every way.
|
| But I do believe they got the syntax wrong - should have been
| "from fs import { readFile }" so that auto-complete works. Python
| got _that_ right, but that 's the only thing Python got right ;)
| ComputerGuru wrote:
| I feel like it's going to be an inevitable language update to
| allow that syntax. I'm surprised TypeScript hasn't succumbed to
| the pressure to support that syntax, but they're really strict
| about where they allow deviations from the JS superset.
| jeswin wrote:
| > I'm surprised TypeScript hasn't succumbed to the pressure
| to support that syntax
|
| They won't do this without consensus in TC39. They shouldn't
| either; that'd be worse than this niggle.
| ComputerGuru wrote:
| Whether they should or not and whether that would be bad or
| not depends on how close of a relationship you believe
| should/does exist between TypeScript and JavaScript l,
| specifically in the TS to JS direction.
|
| If I said language foo _that isn't TS_ but transpiled to JS
| all the same was considering that syntax, people might have
| a different opinion.
| WorldMaker wrote:
| Since Typescript 1.0 it has mostly taken the path of
| wanting to follow TC-39's standards rather than lead
| them. The most notable exception was an experimental flag
| for decorators at too early of a stage that's currently
| playing out in a compatibility war between the too many
| projects depending on the _experimental_ flag _in
| Production builds_ versus the actually standardized
| behavior.
|
| Between that and some remaining warts from <1.0
| mistakes/incorrect assumptions, there's plenty of
| evidence that it is a good thing that other than its type
| system TS focuses on following standards rather than
| trying to lead them.
|
| There's a place for the language "foos" that want to lead
| and champion new standards. As an ecosystem we all seem
| to benefit from Typescript _not_ being that language
| (anymore, mostly not since 1.0 with the few obvious
| mistakes aside). It 's a part of what makes Typescript
| trustworthy as Production tooling. It's also what helps
| make Typescript mostly "cheap" and "unextraordinary" in
| Production build pipelines.
| afiori wrote:
| It is not that big of a deal, you can write
| import {} from "some/package"
|
| And then go back with working autocompletion
| fwlr wrote:
| I think that particular issue could be solved with tooling - if
| you can autocomplete from "package name" to a given exported
| identifier, you must already have a mapping from "package name"
| to "exported identifier" somewhere in your machine's memory;
| duplicate this mapping and swap the keys for values, now
| "exported identifier" points to "package name" as well.
|
| But I do agree that it should be "from 'foo' import { ... }",
| because then the code would look nicer.
| jeswin wrote:
| > I think that particular issue could be solved with tooling
| - if you can autocomplete from "package name" to a given
| exported identifier, you must already have a mapping from
| "package name" to "exported identifier" somewhere in your
| machine's memory; duplicate this mapping and swap the keys
| for values, now "exported identifier" points to "package
| name" as well.
|
| Sorry I don't follow. What the "from ..." syntax does (when
| typing it) is to narrow down 10k possibilities (the set of
| all exported functions in all in-scope modules) down to a few
| dozen. How would this be possible otherwise?
|
| Illustration:
|
| Case 1: import <just about anything is possible here - can't
| auto suggest>
|
| Case 2: from fs import <only fs functions are in scope, start
| autosuggesting on keypress>
| afiori wrote:
| I dislike the assumption that natural languages are a good
| base for the syntax of programming languages,
|
| In my personal contrarian opinion I would have wanted
| something along the lines of import "url"
| with {namedImport}, defaultImport;
|
| With other keywords like import assertion mixed at the same
| level import "url" assert {type:"js"} with
| {namedImport}, defaultImport;
|
| I admit that `with` is not a great choice...
| everforward wrote:
| A core problem here is that modules are generally a unique
| key, but exported identifiers are not. My editor does what
| you're talking about, but can be unhelpful because if I type
| in "create" I get 83,000 results. That would be much more
| helpful if it were pre-filtered by module so I get 6 results
| instead.
| fwlr wrote:
| I'm so used to fuzzy search at this point that it didn't
| even occur to me, but yeah, you're right.
|
| I guess tooling can still provide a solution - a snippet on
| "import", where the first tab stop takes you to the module
| path string, and the next tab stop jumps back to inside the
| braces?
| eyelidlessness wrote:
| I tend to agree, but I've found it mostly doesn't matter as I
| stopped typing import statements almost altogether. I type a
| reference to the thing I want to import, in the place I want to
| use it, choose a suggestion from the editor, and let the editor
| write the import statement as a side effect. It only _doesn't
| work_ when dealing with aliases, and even then only when
| something isn't cached yet.
| eddd-ddde wrote:
| You can type the real name, import it with autocomplete, then
| rename the symbol (f2), which creates the alias.
| eyelidlessness wrote:
| I should've been more clear that I meant import _specifier_
| aliases. Eg in TypeScript, this is often determined by
| `paths` in tsconfig.json. It may also be controlled by
| `imports` in package.json, or any number of other tools and
| configs.
| paulddraper wrote:
| That doesn't work so well for default or wildcard imports.
|
| (I'd argue that default + wildcard imports are bad, but ESM
| went out of its way to have them :shrug:)
| eyelidlessness wrote:
| It works okay for defaults IME, and yeah I generally avoid
| both but especially namespace (wildcard) imports.
| jajag wrote:
| > But I do believe they got the syntax wrong - should have been
| "from fs import { readFile }" so that auto-complete works.
|
| Personally, I prefer the "import x from y" format because it
| makes it easier to visually scan where an import is coming
| from; fair point about auto-complete though.
| tqwhite wrote:
| Really? I have a project that loads modules based on calculated
| values. How will you do that in a pure ESM world?
| zarathustreal wrote:
| You wouldn't, because it's a misunderstanding of what
| "module" means and how they work. It's like saying "maybe I
| need this file" - there is no maybe, you either need it (to
| run conditional logic upon) or you don't.
|
| You get an approximation of conditionally loading a module by
| simply converting everything to ESM and enabling tree-
| shaking. When module loading has no side effects this is
| simple to do. If you're unsure at build time whether you will
| call a certain function from a certain module and that's the
| reason you're conditionally loading it, again enable ESM and
| tree shaking and import the function and call it
| conditionally except do so at runtime. You'll only get
| exactly what you need to avoid the bloat of the whole module
| and your dependency graph will also be more correct as a
| bonus!
| tqwhite wrote:
| You are simply wrong.
|
| I've been a full time NodeJS programmer for fourteen years.
| Module isn't some pure theoretical concept. It is a file
| that exports something in Node.
|
| There's a ton of 'maybe I need this file' in the world. For
| example, I have things that are polymorphic by instance. I
| grab a config entry to decide which of several modules are
| going to be used. The others are completely unnecessary.
|
| You might say, just add a build step that chooses the right
| ones. To which I would say, Are you nuts? Why would I screw
| up a perfectly working paradigm?
|
| To get "an _approximation_ of conditionally loading ".
| recursive wrote:
| Using dynamic import. Here's some documentation to get you
| started.
|
| https://developer.mozilla.org/en-
| US/docs/Web/JavaScript/Refe...
| tqwhite wrote:
| Dynamic import() is asynchronous. I have things that are
| not asynchronous.
|
| To rewrite to be asynchronous gets me exactly _nothing_.
|
| In work that is asynchronous, I use import(). It's fine.
| Also, it gives me nothing but, since that particular thing
| is already async, why not?
|
| This is a terrible, badly thought out thing that was done
| by ECMA that harms a ton of developers and that would have
| been entirely saved if somebody had asked me.
|
| I would have said, add importSync() and there will be
| literally no problems ever again.
| wvenable wrote:
| I've been newly doing a lot more front-end development and I've
| been sort of impressed by the autocomplete. You start typing
| the name you want to import and it autocompletes the name _and_
| module that it comes from. That actually seems more useful to
| me.
| MatthiasPortzel wrote:
| Yep. Especially with relative imports, it's easier to type
| `import { myHelperFunc` and let LSP complete `tion } from
| "../../../util"`.
| samth wrote:
| We considered that syntax, but `from` was not a reserved
| keyword already, whereas `import` was, so the parsing situation
| with the actual syntax was much better.
| cxr wrote:
| import "./foo_bar.js" (for FooBar)
| danvk wrote:
| You can work around this by typing your import statement
| inside-out:
|
| import {} from 'fs';
|
| Then move your cursor back inside the {} and you'll have nice
| autocomplete. Works with object destructuring, too.
| akira2501 wrote:
| They've made zero functional difference to me. What do you like
| about them?
| righthand wrote:
| Why does it matter that people use ES modules instead of
| requires? They're compatible enough. Javascript is weird because
| it has this directive for browsers to keep compatibility, but
| then has proponents for language changes that people try to force
| on everyone through framework/library use and design. All to the
| benefit of someone reading code the way they want to read code.
|
| It hasn't changed because it's not a real problem. This is like
| forcing main as the default branch in git.
| rty32 wrote:
| Well, to begin with, they are NOT compatible, in the general
| sense. What you perceive to be compatible works because of tons
| of (often dirty and ugly) hacks people put together, with many
| issues. (Hint: top-level await). Do your research.
| righthand wrote:
| Hence the "enough" modifier. NodeJS isnt a browser framework,
| do your research.
| tqwhite wrote:
| I could not agree more. In fact, the introduction of ESM has
| been entirely pernicious, causing more problems, not fewer.
|
| Why? Because there is no importSync(). If that existed, it
| would be easy to interoperate.
| tracker1 wrote:
| I think it would have been more prudent if Node had chosen to
| stay closer to Babel compatibility in terms of how it handled
| ESM + Require. I know there were reasons to break things...
| but it could have been smoother.
| tqwhite wrote:
| I don't use Babel so I don't know what that means but I do
| know that I would not be rage-typing if they had simply
| made importSync().
| lenerdenator wrote:
| Surely, this will be the thing tacked onto JavaScript that will
| make it easy to scale and reduce toolchain complexity......
| fwlr wrote:
| Bun put a lot of work into making both "import" and "require"
| always work regardless of whether it's given a commonjs or an ESM
| target. I'd say that's half of the right idea: make _only_ import
| work with anything.
|
| Another angle that might be effective: take the most popular
| aspect of commonjs - `require('extensionless-string')` - and tie
| it to the least popular aspect, .cjs extensions.
| postepowanieadm wrote:
| But why do you want to break half of a working solution?
| tracker1 wrote:
| It's closer to how Babel worked out of the box for half a
| decade before Node added their implementation. It's Node that
| broke a half-working solution.
| fwlr wrote:
| In fairness - given a choice and some time to think, I would
| probably not choose to actively break commonjs. However, if I
| was tasked with increasing ESM adoption, I would go about it
| like this.
| montroser wrote:
| Node should just do like bun and support intermixing both. It was
| a mistake to force this schism -- untold hours of frustration and
| busywork for maintainers and developers with no hope of actually
| "completing" a mythical full transition to the new world.
|
| And for what? In Node specifically, it's not as if esm actually
| solves any real problem! In the greater ecosystem, sure it has
| some benefits, but Node doesn't even have to choose. Just support
| both at once, like bun and build systems have for a while, and
| let's move on from this nonsense.
| Me1000 wrote:
| "Just" is doing a lot of heavy lifting here. It's so
| frustrating watching people think it's just because a bunch of
| smart and hard working people are either lazy or stubborn.
| mardifoufs wrote:
| I'm completely clueless w.r.t js modules, but I'm wondering
| how did Bun manage to do it? Does it work well?
| vlakreeh wrote:
| It works great for 90% of use cases, but getting that last
| 10% to work is really really hard so Bun (and node 22 which
| supports the same thing with an experimental) just throws
| an error in those cases. The most notable thing is
| `require`-ing an async ESM module from CJS, because require
| is a synchronous call you cant just async-ify it trivially.
| preya2k wrote:
| And then here is one of the biggest backend JS frameworks
| (NestJS) clinging to CJS/holding off on migrating to ES modules.
| https://github.com/nestjs/nest/issues/13319
| tqwhite wrote:
| And, if you read that issue, you will see that they are not
| because the only real benefit is spiritual, 'more consistent
| with the future'.
|
| Give them an importSync() and the migration can happen
| incrementally.
| ulrischa wrote:
| The whole node npm ecosystemand tooling is so bad and broken. No
| other language is so frustrating. JavaScript was bad in the early
| years took a good way but is now stuck again. I tried
| webcomponents with lit. All very easy in the beginning. But when
| you try to use an external stylesheet you hit the wall of the
| modern js world: css can not be imported in js without a massive
| tool stack. I whish tue main focus would be tool- and buildless.
| This is really what is lacking
| cxr wrote:
| > The whole node npm ecosystemand tooling is so bad and broken.
| No other language is so frustrating.
|
| Neither Node nor NPM are languages.
|
| > when you try to use an external stylesheet you hit the wall
| of the modern js world: css can not be imported in js without
|
| Uh...?
| replete wrote:
| Completely disagree on getting rid of .mjs, .mts, .cjs, etc. This
| has actually solved a lot of the problems we had of mixed module
| loading IMO
| WorldMaker wrote:
| It's probably going to be a bandaid for a while longer, but the
| problem is "mixed module loading" and we should fix _that_
| problem rather than rely on bandaids long term. The last .cjs
| file I 've needed for a while now in type="module" libraries
| has been for eslint config files and eslint finally supports
| ESM configs. Everything is just .js, as it should be.
|
| I agree with the article that type="module" should be the
| default and once it is the well established default the bandaid
| of .mjs, .cjs, et al extensions should probably provoke a
| deprecation warning rather than being another long-term tech
| debt part of Node.
| jakubmazanec wrote:
| I followed advice of Sindre Sorhus [1] and moved all my packages
| and apps to ESM year ago and couldn't be happier. Only Jest and
| ts-jest were problematic, so I replaced them with Vitest. I also
| never encountered problems because of the so-called dual-package
| hazard [2]; but IMO this isn't that much different than when you
| have two copies of React in node_modules - it's simply an
| npm/dependencies problem, not ESM problem.
|
| [1]
| https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3...
|
| [2]
| https://nodejs.org/api/packages.html#packages_dual_package_h...
| simlevesque wrote:
| People never wanna work or learn. It's not even that big a pill
| to swallow.
| plopz wrote:
| not being able to mock es modules in tests is a real pain
| o11c wrote:
| As someone who only dabbles in JS, one problem is that ESM makes
| polyfills impossible. And polyfills are mandatory in the JS
| ecosystem.
|
| It's quite meaningful for dependencies to be _fetched_
| asynchronously, but sometimes you really need something to be
| _executed_ in the order it 's written.
| norman784 wrote:
| I would argue that polyfills are not needed anymore, you are
| safe using ES2022 or even ES2023.
| tracker1 wrote:
| Mostly agree with the above, outside some ES3-ish scripting
| environments (Adobe and others), polyfills for a lot of
| functionality isn't needed strictly for JS support. And even
| then, can still be part of bundling or shimmed outside your
| application script(s).
|
| And if you're bundling, then you can add them into the
| process. I've been avoiding most things that could require a
| polyfill since 2018 or so anyway as green browsers are pretty
| feature complete. As much as I'd like the F# style pipelines,
| and there are a couple other niceties, I don't miss much.
| Sephr wrote:
| Polyfills are often necessary because new features are still
| added to the standard library, and runtimes all have varying
| levels of support for new features.
| dbalatero wrote:
| False, I just added one the other day for the scheduler API.
| TheRealPomax wrote:
| At the very least, they finally should switch over to ESM-by-
| default and announce that 2 or 3 major versions in advance. "From
| Node 25 all code is assumed ESM unless you have `"type":
| "commonjs"` in your package.json" is not a particularly difficult
| message to send out and would stop people from writing new
| projects using the now legacy CJS (super great that it existed
| back when JS had nothing even close to a dependency model, but it
| should have been retired once ESM went from stage 4 to "this is
| literally and officially how JavaScript works")
| pictur wrote:
| if you look at most npm packages, you can see that versions that
| do not support es modules are downloaded more. and it's been like
| this for years. an example package:
| https://www.npmjs.com/package/p-queue?activeTab=versions
| h1fra wrote:
| The fact that `npm init` still not default to `type: module` is
| baffling
| meego wrote:
| Barely a third of "high-impact" packages on npm are ESM. And
| that's with a generous definition of what an ESM package is. [1]
|
| [1]: https://github.com/wooorm/npm-esm-vs-cjs
| 999900000999 wrote:
| I'm tempted to say we need a complete reset of the NodeJS
| ecosystem.
|
| It will never happen because it would require coordination and
| money, but instead of having millions upon millions of different
| NPM packages, many of which are downright harmful, we should have
| a careful selection of maybe the top 20,000 or so.
|
| And then maybe call the next generation of node something else,
| maybe ProJS.
| paulddraper wrote:
| Isn't the problem that ESM is proving almost too much of a
| reset?
|
| I'm not sure I understand what you're going for.
| PaulHoule wrote:
| This is timely to me because I am in the middle of modernizing a
| project that was ejected from CRA years ago and now won't build
| in Node 18.
|
| I've worked on a few big React projects but haven't really looked
| much into how the build works, I found out upgrading one thing
| forced me to upgrade other things and I wound up making a lot of
| changes by hand to the build scripts and figured I'd probably
| screw something up. Dependencies changing from CommonJS to ESM
| was probably the most common problem that can frequently solved
| by version bumps (at risks of adopting changes you don't want)
|
| At some point I decided to try the alternate path of switching to
| Vite for a build system since I've had good luck working with it
| for some VR side projects.
|
| It's funny how you can code on front-end Javascript and not need
| to learn about CommonJS until something like this hits.
| apitman wrote:
| My only complaint about the current state of ESM is that I can't
| figure out how to resolve the following:
|
| 1. I'm developing a library that depends on d3js
|
| 2. I want the library to be usable without any build tools. Just
| clone my repo and host the files from a static server. Or just
| import directly from jsdelivr
|
| 3. I also want people to be able to use NPM to install my library
| if they so choose
|
| The problem is if I vendor d3js, then developers who consume my
| library via NPM might end up with 2 copies of d3js in their app,
| if their app also uses d3 directly. But if I don't vendor it,
| then my ESM-only users have to use an import map to resolve the
| bare specifier in the browser, which is kind of ugly and
| confusing.
|
| More details: https://stackoverflow.com/q/78645299/943814
| noiv wrote:
| That's when I started vite first time. I think it's the build
| tool closest to no build tool.
| tobyhinloopen wrote:
| It's such a waste of time to have this change so often. Can we
| just stop changing things? Require and module.exports was fine.
| 123yawaworht456 wrote:
| old thing bad
|
| new thing good
| zazaulola wrote:
| Jesus, what the hell?!
|
| Why do you dislike `require()` so much?
|
| Just imagine a person who doesn't write modules in Node.JS, but
| he would like his small scripts to be placed in one JS-file -
| without any additional directories and `package.json`. His
| script, for example, updates data for a desktop widget, is easily
| bypassed by standard nodejs modules and he has hundreds of such
| scripts in his folder. Why does he need all this `import`
| overhead?
___________________________________________________________________
(page generated 2024-06-20 23:01 UTC)