Live data from Hacker News

ES modules are terrible

gist.github.com

141–150 of 175 posts

Re: ES modules are terrible

#141
post #78

Earlier quoted context omitted.

> I have been doing nodejs backend development for the past 10 years and I have no idea why ES module are needed and who is using them ES modules are part of the Ecmascript spec. DENO uses them. Node.js modules aren't part of the ES spec.

I see, so a front end thing indeed :) (and yes deno, which I feel the main purpose is to bring the problems and debates of the front end devs, in an otherwise much saner js backend end world ^^ )

[deleted]

Re: ES modules are terrible

#142
post #85

Earlier quoted context omitted.

QUIC / HTTP3 does not fix the roundtrip wait times caused by dependencies - if 'a.mjs' imports 'b.mjs' which in turn imports 'c.mjs'... you still need two roundtrips to load all three. only a bundler can fix that (or a hypothetical process which would set up preloads for all required libraries, but that would just be a bundler without the actual bundle creation step)

An ES module-aware server can avoid that problem by using HTTP Server Push[1], but I haven't seen a production-quality implementation of that, only proof-of-concepts. [1] https://medium.com/@nikita.malyschkin/the-future-of-web-depl...

Server push is being deprecated because it was far to hard to implement correctly. A server that knows the dependency graph could inject into the HTML though.

Re: ES modules are terrible

#143

Earlier quoted context omitted.

This is not true at all. For every module you can parse out and load the module's imports in parallel. As you traverse the graph the known and loadable module frontier can grow much wider. The only way it would be serial is if every module only imported one other module.

Note how I was specifically talking about depth-wise .

Fair, though that wasn't clear.

So then even without modulepreload or bundling, it's not always going to be true that the longest import depth is the limiting factor. Earlier loaded modules can still be parsed in parallel while dependencies are fetched, and completed subtrees can be linked and evaluated. Given that modules are deferred and can be imported early, there's often time for parallel work.

Re: ES modules are terrible

#144

Earlier quoted context omitted.

> SRI really should be done out of band. Inline SRI would require far to frequent cache invalidation and isn't compatible with package manager workflows where you don't know the exact version of a file you'll depend on. A tool rather should build up an SRI manifest similar to a package lock. This has been discussed several times in module and import map threads. If you are introducing a tool, then you should be bundl…

Your complaints seem to have far less to do with JS modules and much more to do with the lack of native bundling in the platform. From my point of view, the goal posts that keep moving are the ones put up by anti-JS-modules folk because they keep comparing unbundled JS modules vs bundled CJS. Unbundled CJS would perform far worse than standard JS modules by all these measures, but somehow gets a pass because it has t…

> From my point of view, the goal posts that keep moving are the ones put up by anti-JS-modules folk because they keep comparing unbundled JS modules vs bundled CJS. Unbundled CJS would perform far worse than standard JS modules by all these measures, but somehow gets a pass because it has to be bundled.

A feature that by default encourages use that is both slower and less secure on the web is a bad feature, full stop. The SRI problem is not even solved yet. Shipping import statements in production leads to slower websites. This is exacerbated by the fact that the syntax looks synchronous but behaves asynchronously. As someone who clearly cares much more about the browser environment than the node environment, these problems should resonate with you, regardless of the situation with node. import isn’t good even if you only consider the web.

> What module feature could possibly have solved the waterfall problem?

I will give one example of an alternative approach that could have been taken: start with the expression form of import(), ship it alongside top-level await, and hold off on the statement form until after we could see how this was used (you could even restrict it to only taking string literals if you want to begin with, doesn’t make a super difference for this argument, but I can see arguments for that). Here are the benefits:

1. You get everything you get with normal import, you just type await import() and use normal declarations with destructuring. There’s no ergonomic difference except for a couple extra characters, and it is less syntax to learn since you don’t need to learn the almost, but not quite, identical importing declaration destructuring.

2. There’s no weird bifurcation of “load semantics” left as an exercise to the implementer, it’s well defined under Promise semantics and gives us time to determine if we need something fancier.

3. This would have punted a lot of meta issues until later, including “what happens if a module throws an error during load?” And “what happens with recursive imports?” All of these questions are less critical in the expression form where the user has recourse (they can wrap it in try/catch! There can be a user accessible cache, etc.) However, with a top level black box statement these become must fix blockers because you can’t just say “oh the user has many good options”, you have to determine some one-size-fits-all complicated behavior.

4. The fundamental asynchronous nature of import() is not hidden from you in a way that makes you feel like you’re doing something fast, and is the actual issue I have with “the bundling debate”. The await makes it clear that this is a “blocking” (to code after it) asynchronous operation that you probably shouldn’t ship in production, as opposed to the situation now where not only do people not understand this, but we continue to add more features that perpetuate this myth (like module preload link tags that are still slower than bundling but probably require you to use a build tool so what’s the point?).

5. We would have had REPL support on day 1! Both in the browser console and in node. This would have been so helpful for debugging.

All in all, this would have been a great incremental approach that solved the immediate problem of needing something better than evaling the text result of an XMLHttpRequest. It gives you all the functionality of the import statement without the facade of a synchronous feature. It would have prioritized top-level await, made features we’re thinking about now much easier to introduce too (like inline modules), and would have almost certainly already been incorporated in node since there would have been no years of going back and forth since you can’t tell what’s a module without parsing the whole file first problem which is what lead to the whole .mjs mess.

This probably would have had to wait until after ES6 shipped since it fundamentally relies on async/await, but that’s actually a huge part of the point: we wouldn’t have shipped a fundamentally async feature prior to getting our async story straight in the language. A post-async JS mindset would have lead to many different decisions. Despite this delay though, there’s a good chance it would have been fully adopted everywhere much sooner, and would have been much easier to transpile, since it’s “just a function” with syntax restrictions.

Just because something took a long time doesn’t mean it wasn’t rushed.

Re: ES modules are terrible

#146

Earlier quoted context omitted.

If you do that you're stuck with round trip times all the way down the dependency tree. HTTP/2 reduces the overhead of that, but doesn't eliminate it, so now you've added a bunch of loading time to your site.

I thought that as well, until I read this: https://www.sitepoint.com/file-bundling-and-http2/ https://medium.com/@asyncmax/the-right-way-to-bundle-your-as...

I don't see a counterargument here. "It's fast" doesn't change the fact that using 'native' imports instead of bundles means you're still adding the round trip time for the browser to request each set of dependencies all the way down the dependency tree.

Re: ES modules are terrible

#147
post #50

HTTP/2 uses a single connection for all modules, no?

If you use 'native' imports in that way instead of bundles, you're still stuck with artificially delayed loading times because the browser has to parse your code, request the first layer of dependencies, parse that code, request the second layer of dependencies, etc.

Re: ES modules are terrible

#148

Earlier quoted context omitted.

Note how I was specifically talking about depth-wise .

Fair, though that wasn't clear. So then even without modulepreload or bundling, it's not always going to be true that the longest import depth is the limiting factor. Earlier loaded modules can still be parsed in parallel while dependencies are fetched, and completed subtrees can be linked and evaluated. Given that modules are deferred and can be imported early, there's often time for parallel work.

I'm not following. Dependencies can be nested, so you cannot assume that a dependency by a given name can be satisfied by a previously loaded dependency by the same name. Which means you still need as many serial roundtrips as there are depth levels, whether you parse in parallel or not.

Sure, you can cut down on the delay introduced by the parsing, but 10 depth levels over a 100ms connection is still going to take a second to fetch, because you simply can't know the N+1th dependency until you have at least completed the Nth roundtrip.

Re: ES modules are terrible

#149
post #101

This thread and summary are written by someone who has no clue what they're doing in ECMAScript; and who's probably enjoying the fucked up mess that the babel ecosystem created. I'm not gonna dig into that, because reading any polyfill in babel's ecosystem speaks for themselves on how messy, hacky, and actually not working-as-specified most parts are. Instead I'm gonna try to go back to the topic. I think that in pra…

> - "export already_imported_variable;" - why the HECK is this not in the specification? Having to declare new variable names for exports makes the creation of "index" files so damn painful. This syntax could fix this. You can do: export {already_imported_variable}

...which is a default export, not a named export, as I already explained. My point was about the lack of exporting named exports without the need to declare variable names.

Your solution will work only once in a file, therefore it is useless to batch-export lots of imports for the mentioned use case of an "index" file that exports all your classes and definitions.

Re: ES modules are terrible

#150
post #103

Earlier quoted context omitted.

Hm, I wonder if this could be circumvented by doing timing attacks against the CDN cache? That's still shared between domains...

It is not: https://developers.google.com/web/updates/2020/10/http-cache... https://developer.mozilla.org/en-US/docs/Web/Privacy/State_P...

That's the cache in the browser, not the cache in the CDN.
Post reply on HN