Live data from Hacker News

ES modules are terrible

gist.github.com

131–140 of 175 posts

Re: ES modules are terrible

#131

question: // ... if (condition) { const x = require('../../../hugeFuckingLibraryThatTakesSeveralSecondsToLoadUponColdStart') // do something with x } // ... assume I don't give a fuck about nerd bullshit and I just want the code to be simple and the program to run fast (which it does when !condition because it doesn't need to load hugeFuckingLibrary), can I replicate this behavior with ESM?

Well since you asked so "fuckin" nicely /s

    if( condition ){
      import('../../../hugeFuckingLibraryThatTakesSeveralSecondsToLoadUponColdStart').then( x => {
          //do something with x
      })
    }
> ...nerd bullshit...

I hate to break it to you darling, but programming is nerd bullshit.

edit: alternate that might too much "nerd bullshit", but uses async/await if the surrounding code is an async function:

     async function doSomeStuff()
    {
        if( condition ){
          const x = await import('../../../hugeFuckingLibraryThatTakesSeveralSecondsToLoadUponColdStart');
          //do something with x
        }
    }

Re: ES modules are terrible

#132
post #56
post #14

> And then people go "well you can statically analyze it better!", apparently not realizing that ESM doesn't actually change any of the JS semantics other than the import/export syntax, and that the import/export statements are equally analyzable as top-level require/module.exports. ... "But in CommonJS you can use those elsewhere too, and that breaks static analyzers!", I hear you say. Well, yes, absolutely. But tha…

Unless I'm missing something, the exercise is pretty simple, and could be done with grep in a sane codebase (find all require without indentation and with a single string literal inside the parenthesis)

It's a bit more complicated than that because you'd not want to match such things if eg. they exist inside of another string literal; but the actual implementation of 'dependency collection' in various bundlers isn't too far off from this. They just often do an AST match instead of a string match.

Re: ES modules are terrible

#133

> And then people go "but you can use ESM in browsers without a build step!", 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'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. T…

It's a fundamental technical constraint of any tool-less setup. At some point you need to traverse the dependency tree by parsing modules and following imports, and your choice is to do that either:

1) on the client, across the network, one roundtrip for every level of depth, or 2) in a build environment, directly on the filesystem

Option 2 means you need some kind of build tool to make it work, and by that point it doesn't really matter anymore whether the tool just traverses the dependencies and makes a list of filenames, or also concatenates their contents into a bundle.

And that is why the fundamental premise of ESM cannot work; there are no technical options besides those two. If you want to avoid network roundtrips, you must have build tooling. No way around it.

Re: ES modules are terrible

#134
post #108

Earlier quoted context omitted.

Hi, author here. I'm going to ignore the personal attacks and simply point out that my dev build processes typically have a startup time of under 5 seconds even for large projects, and a rebuild time of under 500ms. This is with Browserify. If you are having very slow build times with your existing toolchain, the problem isn't the bundling, which is an extremely fast operation. It's almost certainly going to be one s…

"Wie man in den Wald hinein ruft, so schallt es heraus" since your from NL it should be easy to translate. These heavy plugins are usually for old browsers to also run in them. That is the only job ob babel. CJS has some deeper problems. - Check if your fav CJS lib freezes the objects? - ESM is more http friendly (mime type)

The build times I listed are including a Babel plugin.

Re: ES modules are terrible

#135

Earlier quoted context omitted.

Worse, even if they were all fetched in parallel, you would still see terrible loading times simply because a dependency graph can only be traversed depth-wise serially. Doesn't matter what network protocol you use or how parallel it is.

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.

Re: ES modules are terrible

#136

Earlier quoted context omitted.

It is absolutely not excellent, unless you restrict yourself solely to whether there is a checkmark next to the browser name in mdn. It is very buggy, very difficult to debug, and as I mentioned in another comment, missing serious features (like no subresource integrity which, means we’re encouraging people to use a much less secure system of importing scripts in many cases!) > It really is the whole point. TC39 was…

I've been using almost exclusively standard modules for years and they work quite well. Old crashers and cache problems I was aware of have been fixed for many years now. I don't know what debugging problems there are that wouldn't exist in CJS. At least with native modules you can see individual requests in the network panel while you're working and individual files in the sources panel while debugging. That alone i…

> 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 bundling your code, not creating more metadata files to load! Bundled code has repeatedly proven to load faster than ESM code using whatever HTTP 3 prefetch mumbo jumbo you throw at it, that no one actually uses in practice anyways. If you have a tool chain, then the answer is easy: don’t delay fetches and create more HTTP requests and roundtrips! As I mentioned in another comment, the sheer ridiculousness of this is demonstrated in the feature [1], where I kid you not the actual recommendation for having performant dependencies is to litter your HTML file with a link tag for ever JS file that’s imported. We’re right back to where we started with a top level script tag for every script! Argh! But I know, now the recommendation is “oh no silly, your build tool should just create your 100 link tags”. Again, why? If you’re using a build tool a bundled file is way faster than waiting for link tags to get parsed to issue a bunch prefetches and on and on. It’s so frustrating to discuss ESM because the goal posts kerp bouncing between this being an “easy to use feature that removes the need for build tools” only to have every issue with it hand-waived away as trivially solvable by a build tool that ultimately creates a worse end-user load experience than what we already have.

> The fact that Node has some JS module / CJS interop issues (and really only when you try to use JS modules from CJS, the other way is fine) is Node's problem, not TC39's. There's really nothing that TC39 could have done here because synchronous require() is the fundamental problem.

I think part of the disagreement stems from the fact that you believe my position is that we should have “done nothing” or that the only options were “the system we shipped” or “just do it the node way” or something. That’s not the case at all. I am all for a standard system and I recognize the problems with require(). It is simply the case that a design that took into account the requirements of node could very well have served both systems. These aren’t the only two possible require systems imaginable, but an API that exclusively looks at only one set of constraints, despite billing itself as a general purpose solution, will not generate the best end result. This is shown by the several bandaids that had to be added after the fact to import and could have been avoided if considered beforehand.

1. https://developers.google.com/web/updates/2017/12/moduleprel...

Re: ES modules are terrible

#137
post #14

> And then people go "well you can statically analyze it better!", apparently not realizing that ESM doesn't actually change any of the JS semantics other than the import/export syntax, and that the import/export statements are equally analyzable as top-level require/module.exports. ... "But in CommonJS you can use those elsewhere too, and that breaks static analyzers!", I hear you say. Well, yes, absolutely. But tha…

> Yes, dynamic imports exist but they are sort of an exotic feature that you would only use in special situations.

They're also decidedly inconvenient to use in most situations, because they return a Promise (unlike require()), which means anything that depends on them has to itself be deferred. This further discourages using them unless you really need to.

Re: ES modules are terrible

#138

Earlier quoted context omitted.

I've been using almost exclusively standard modules for years and they work quite well. Old crashers and cache problems I was aware of have been fixed for many years now. I don't know what debugging problems there are that wouldn't exist in CJS. At least with native modules you can see individual requests in the network panel while you're working and individual files in the sources panel while debugging. That alone i…

> 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 to be bundled.

What module feature could possibly have solved the waterfall problem? The only options are manifests and bundling. IE, you can't magically tell a browser what it should load without telling it what it should load. modulepreload is essentially a manifest and Web Bundles are bundles, so there are solutions covering the space. Browsers should get behind Web Bundles, asap, since that would also solve many problems for caching, CSS and other assets.

The problem I have with this debate is that JS modules get criticized for being able to work without bundling at all, when that's purely a positive and they still can be bundled for performance.

If you don't like the unbundled workflow, don't use it. It's still useful to have a standardized syntax and semantics, and very useful for those of us who do want to use them unbundled: for simple cases, dev environments, or combined with features like prefetch/preload.

Re: ES modules are terrible

#139
post #31

Earlier quoted context omitted.

Statically analyzable tree. In CJS you have to depend on people not doing strange things to their `module.exports` and you are left with heuristics.

This is not actually a meaningful benefit that ESM has in practice, as I've explained in my article.

> as I've explained in my article

Not convincingly.

Firstly, static imports are markedly different to top-level require due to module scoping: e.g. tree-shaking isn't stable with most "statically-analysed" top-level requires due to potential side-effects.

Secondly, handwaving dynamic imports as the ES Modules equivalent to non-top-level require doesn't pass the smell test. Dynamic imports are a deliberately separate syntax and mechanism to static imports, whereas require isn't differentiated. They are also, notably, async.

Post reply on HN