Hacker news

  • Top
  • New
  • Past
  • Ask
  • Show
  • Jobs

The three pillars of JavaScript bloat (https://43081j.com)

456 points by onlyspaceghost 1 day ago | 267 comments | View on ycombinator

auxiliarymoose 1 day ago |

I really think writing dependency-free JavaScript is the way to go nowadays. The standard library in JS/CSS is great. So are static analysis (TypeScript can check JSDoc), imports (ES modules), UI (web components), etc.

People keep telling me the approach I am taking won't scale or will be hard to maintain, yet my experience has been that things stay simple and easy to change in a way I haven't experienced in dependency-heavy projects.

stevoski about 20 hours ago |

Well-written article, manages not to sound rant-y while describing the problem well.

I feel like part of the blame for the situation is that JavaScript has always lacked a standard library which contains the "atomic architecture" style packages. (A standard library wouldn't solve everything, of course.)

andai 1 day ago |

Great article, but I think these are all marginal.

The main cause of bloat is not polyfills or atomic packages. The cause of bloat is bloat!

I love this quote by Antoine de Saint-Exupéry (author of the Little Prince):

"Perfection is achieved, not when there is nothing left to add, but nothing to take away."

Most software is not written like that. It's not asking "how can we make this more elegant?" It's asking "what's the easiest way to add more stuff?"

The answer is `npm i more-stuff`.

zdc1 1 day ago |

A lot of this basically reads to me like hidden tech debt: people aren't updating their compilation targets to ESx, people aren't updating their packages, package authors aren't updating their implementations, etc.

Ancient browser support is a thing, but ES5 has been supported everywhere for like 13 years now (as per https://caniuse.com/es5).

rtpg about 24 hours ago |

I think on the first point, we have to start calling out authors of packages which (IMO) have built out these deptrees to their own subpackages basically entirely for the purpose of getting high download counts on their github account

Like seriously... at 50 million downloads maybe you should vendor some shit in.

Packages like this which have _7 lines of code_ should not exist! The metadata of the lockfile is bigger than the minified version of this code!

At one point in the past like 5% of create-react-app's dep list was all from one author who had built out their own little depgraph in a library they controlled. That person also included download counts on their Github page. They have since "fixed" the main entrypoint to the rats nest though, thankfully.

https://www.npmjs.com/package/has-symbols

https://www.npmjs.com/package/is-string

https://github.com/ljharb

SachitRafa 1 day ago |

The cross-realm argument for packages like is-string is the one I find hardest to dismiss, but even there the math doesn't add up. The number of projects actually passing values across realms is tiny, and those projects should be the ones pulling in cross-realm-safe utilities, not every downstream consumer of every package that ever considered it. The deeper problem with Pillar 2 is that atomic packages made sense as a philosophical argument but broke down the moment npm made it trivially easy to publish. The incentive was "publish everything, let consumers pick what they need" but the reality is consumers never audit their trees,they just install and forget. So the cost that was supposed to be opt-in became opt-out by default. The ponyfill problem feels most tractable to me. A simple automated check "does every LTS version of Node support this natively?" could catch most of these. The e18e CLI is a good start but it still requires someone to run it intentionally. I wonder if something like a Renovate-style bot that opens PRs to remove outdated ponyfills would move the needle faster than waiting for maintainers to notice.

burntoutgray 1 day ago |

I have a single pillar, admittedly for in-house PWAs: Upgrade to the current version of Chrome then if your problem persists, we'll look into it.

kigiri about 9 hours ago |

I work on a ~9y old nodejs codebase, have none of those issues, we have 8 dependencies, this is fully resolved tree.

One to generate zip files, one for markdown parsing, connecting to postgres, etc... most of them have no sub dependencies.

We always reach out first to what nodejs lib have, try to glue ourself small specific piece of code when needed.

The app is very stable and we have very few frustrations I used to have before. Note that we used to have way more but bit by bit removed them.

Now I would whitelist anything from the deno std* lib, they did a great job with that, even if you don't use Deno, with what ever your runtime provide plus deno std you never need more than a few packages to build anything.

JS is doing pretty good if you are mindful about it.

AltruisticGapHN about 18 hours ago |

"some people apparently exist who need to support ES3 - think IE6/7, or extremely early versions of Node.js"

Seriously what kind of business today needs to support ES3 browsers? Even banking sites should refuse to run on such old devices out of security concerns.

prinny_ about 18 hours ago |

Everyone trash talking the JS ecosystem without contributing the slightest to the conversation would benefit a lot if they read https://www.artmann.co/articles/30-years-of-br-tags in order to understand the evolution of the language and its tooling.

Nobody argues what we currently have is great and that we shouldn't look to improve it. Reducing it to "JS developers bad" is an embarrassing statement and just shows ignorance, not only of the topic at hand, but of an engineering mindset in general.

g947o about 16 hours ago |

https://immich.app/cursed-knowledge

> There is a user in the JavaScript community who goes around adding "backwards compatibility" to projects. They do this by adding 50 extra package dependencies to your project, which are maintained by them.

> https://github.com/immich-app/immich/pull/10690

wheattoast about 18 hours ago |

“Alternatively, what’d be really nice is if they upgraded“

Easy enough for y’all with techie salaries, but as one of the millions of poor folks whose paychecks barely (or don’t even) pay the bills, it’d be really nice if we didn't have to junkheap our backbreakingly expensive hardware every few years just cuz y’all are anorexically obsessed with lean code, and find complex dependancies too confusing/bothersome to maintain.

baubino about 4 hours ago |

I feel vindicated by this recent turn back to vanilla js (which I never left).

socalgal2 about 10 hours ago |

There was a time I'd use dependencies for trivial things like copying a file during building or running things in parallel. Now I just script those in js and call that js from my build. Even testing is now included in node so I stopped using a testing framework.

derodero24 about 15 hours ago |

The polyfill treadmill is the one that gets me. I work on native Node addons so the JS layer is basically just a loader and types — no polyfills, no transpilation targets. Really puts into perspective how much of a typical npm package is compatibility layers for environments nobody actually runs anymore. josephg's right that just tracking Node's EOL schedule would kill a huge chunk of this overnight.

procaryote about 21 hours ago |

The most frustrating thing with the "Atomic architecture" bit with tiny packages is how obviously stupid it is. Any borderline sane person should look at isOdd/isEven and see that it's an awful idea

Instead they've elevated it to a cultural pillar and think they've come up with a great innovation. It's like talking to antivaxers

algolint about 18 hours ago |

It's interesting how we've reached a point where 'vanilla' is seen as an obscure domain of knowledge. The 'gravity' of frameworks like React is so strong that for many new developers, the framework IS the web. Breaking out of that mindset often reveals that the browser has actually evolved quite a bit and can handle a lot of what we used to reach for libraries for, especially with Web Components and CSS Grid/Flexbox being so mature now.

DanielHB about 15 hours ago |

> Atomic architecture

> [...]

> Each of these having only one consumer means they’re equivalent of inline code but cost us more to acquire (npm requests, tar extraction, bandwidth, etc.).

It costs FAR more than dep install time. It has a runtime cost too, especially if in frontend code using bundlers where it also costs extra bundlespace and extra build time.

il-b about 24 hours ago |

The elephants in the room are react and webpack.

tylerchilds about 13 hours ago |

I agree, but would also posit a parallel The Three Pillars of JavaScript Ecosystem Bloat

for example, javascript runs in a browser or on microcontrollers. you can write code that work for both natively [1].

TypeScript-- a mechanism that needs to compile first into javascript

React-- a mechanism that needs to compile first into javascript

Configuration-de-jour-- Depending on how you need to string your TypeScript and React together, there's a thing you need to manage your javascript managers. Vite is the best option in this field, since it recognizes exposing tools to fine tune how to optimize your resulting javascript from your typescript and react is a terrible idea that leads to mass fragmentation on a global scale for what it even means to "spin up a js project"

In conclusion, is javascript a compile target like assembly or a language that people can handcode to eek performance out of like assembly?

[1]: https://github.com/bellard/mquickjs

est about 24 hours ago |

More like a nodejs bloat rather than JS bloat.

For personal objects I always prompt the AI to write JS directly, never introduce nodejs stack unless absolutely have to.

Turns out you don't always need Nodejs/Reactto make a functional SPA.

skrtskrt about 24 hours ago |

the fact that you can just redefine Map in a script is mind boggling

wiseowise about 20 hours ago |

> Using the e18e CLI to detect replaceable dependencies

https://github.com/e18e/cli

That’s awesome. Could be hooked as a pre-commit for agents to do the grunt work of migration.

skydhash 1 day ago |

Fantastic write up!

And we're seeing rust happily going down the same path, especially with the micro packages.

lerp-io about 21 hours ago |

just make react native to browser and everything else thats a one off can be ai generated

IAmLiterallyAB about 23 hours ago |

For the old version support. Why not do some compile time #ifdef SUPPORT_ES3? That way library writers can support it and if the user doesn't need it they can disable it at compile time and all the legacy code will be removed

undefined about 24 hours ago |

undefined

turtleyacht 1 day ago |

It would be interesting to extend this project where opt-in folks submit a "telemetry of diffs," to track how certain dependencies needed to be extended, adapted, or patched; those special cases would be incorporated as future features and new regression tests.

Someday, packages may just be "utility-shaped holes" in which are filled in and published on the fly. Package adoption could come from 80/20 agents [1] exploring these edges (security notwithstanding).

However, as long as new packages inherit dependencies according to a human author's whims, that "voting" cycle has not yet been replaced.

[1] https://news.ycombinator.com/item?id=47472694

sheept 1 day ago |

I wonder this means there could be a faster npm install tool that pulls from a registry of small utility packages that can be replaced with modern JS features, to skip installing them.

casey2 about 22 hours ago |

There is a clear and widespread cultural problem with javascript. Sites should think seriously hard about server side rendering, both for user privacy (can't port the site to i2p if you drop 5MB every time they load a page) and freedom. Even this antibloat site smacks you with ~100KB and links to one that smacks you with ~200KB. At this rate if you follow 20 links you'll hit a site with 104 GB of JS.

stephenr about 24 hours ago |

The primary cause of JS bloat is assuming you need JS or that customers want whatever you're using it to provide.

For $client we've taken a very minimal approach to JavaScript, particularly on customer facing pages. An upcoming feature finally replaces the last jquery (+ plugin) dependent component on the sales page, with a custom implementation.

That change shaved off ~100K (jquery plus a plugin removed) and for most projects now that probably seems like nothing.

The sales page after the change is now just 160K of JS.

The combination of not relying on JS for everything and preferring use-case-specific implementations where we do, means we aren't loading 5 libraries and using 1% of each.

I'm aware that telling most js community "developers" to "write your own code" is tantamount to telling fish to "just breathe air".

wonnage about 20 hours ago |

An underappreciated source of bloat is module duplication stemming from code splitting. SPAs have a bad rep because you don't expect to download an entire app just to load one page on the web. You can solve this by code splitting. But if you just naively split your app by route, you'll end up with duplicate copies of every shared module.

Bundlers handle this by automatically creating bundles for shared modules. But if you optimize to avoid all shared modules, you end up with hundreds of tiny files. So most bundlers enforce a minimum size limit. That's probably fine for a small app. But one or more of these things happens:

1. Over time everybody at the company tends to join one giant SPA because it's the easiest way to add a new page. 2. Code splitting works so well you decide to go ham and code split all of the things - modals, below-the-fold content, tracking scripts, etc.

Now you'll run into situations where 20 different unrelated bundles happen to share a single module, but that module is too small for the bundler to split out, and so you end up downloading it N times.

sylware about 16 hours ago |

It is not javascript itself (until the interpreter is written in plain and simple C or similar), it is the abomination of the web engine, one of the 2.5 from the whatng cartel.

sipsi 1 day ago |

i suggess jpeg.news dot com

steveharing1 about 21 hours ago |

So the guy who called JS, a weird language was not wrong huh?

Rithan about 2 hours ago |

[dead]

leontloveless 1 day ago |

[dead]

irenetusuq about 20 hours ago |

[dead]

ctvdev about 18 hours ago |

[dead]

huhulove1990 about 15 hours ago |

[dead]

undefined about 20 hours ago |

undefined

undefined about 20 hours ago |

undefined

undefined about 21 hours ago |

undefined

undefined about 21 hours ago |

undefined

undefined about 21 hours ago |

undefined

butILoveLife about 16 hours ago |

[dead]

hknzerodark1 about 17 hours ago |

[dead]

hknzerodark1 about 20 hours ago |

[dead]

grishka about 22 hours ago |

Yes, of course the tiny packages cause some of the bloat. As mainly a Java developer being pretty paranoid about my dependency tree (I'm responsible for every byte of code I ship to my users, whether I wrote it or not), I'm always blown away by JS dependency trees. Why would you reach for a library for this three-line function? Just write it yourself, ffs.

But the real cause of JS bloat is the so-called "front-end frameworks". Especially React.

First of all, why would you want to abstract away the only platform your app runs on? What for? That just changes the shape of your code but it ends up doing the same thing as if you were calling browser APIs directly, just less efficiently.

Second of all, what's this deal with mutating some model object, discarding the exact change that was made, and then making the "framework" diff the old object with the new one, call your code to render the "virtual DOM", then diff that, and only then update the real DOM tree? This is such an utterly bonkers idea to me. Like, you could just modify your real DOM straight from your networking code, you know?

Seriously, I don't understand modern web development. Neither does this guy who spent an hour and some to try to figure out React from the first principles using much the same approach I myself apply to new technologies: https://www.youtube.com/watch?v=XAGCULPO_DE

krmbzds about 24 hours ago |

JavaScript bloat is downstream of low FED interest rates.

general_reveal about 19 hours ago |

Anyone want to tell him programming languages don’t matter anymore?

pjmlp about 22 hours ago |

What about only writing JavaScript when it is actually required, instead of SPAs for any kind of content?

There will be almost no bloat to worry about.

deanc about 19 hours ago |

I can't help but think that whenever we have these discussions about dependency hell in the JS ecosystem that the language moves too slowly to add things to stdlib. For me, this is where bun fills the gap and they continue to pump out core stdlib packages that replace widely used dependencies. I'd really like to see Node at least do this more.

onion2k about 21 hours ago |

Fallback support is a legitimate reason for additional code being in the bundle, but it's not 'bloat' because it's necessary. In an ideal world every website would generate ES5, ES6, and ES2025 bundles and serve the smallest one that's necessary for the app to run based on the browser capabilities, but that is genuinely quite hard to get right and the cost of getting it wrong is a broken app so it's understandable why devs don't.

The other two, atomic architecture and ponyfills, are simply developer inexperience (or laziness). If you're not looking at the source of a package and considering if you actually need it then you're not working well enough. And if you've added code in the past that the metrics about what browsers your visitors are using show isn't needed any more, then you're not actively maintaining and removing things when you can. That's not putting the user first, so you suck.