Hacker News new | past | comments | ask | show | jobs | submit login
The Shocking Immaturity of JavaScript (dev.to)
74 points by mjgardner on Oct 10, 2021 | hide | past | favorite | 76 comments



I did web dev for a few years using Angular + various other tools, and yes, it was nightmarish.

I had to come back to it briefly recently. But using "boring" Typescript, esbuild and preact, I have to say the experience was an immeasurable improvement. Verging on pleasant even. Everything was well-documented with strong Stackoverflow coverage.

So, boring > shiny


You probably already know this, but for anyone wanting to do this: esbuild does not do any type checking, so TypeScript with pure esbuild (without a separate tsc step) is only half useful (it gives you better autocompletion, but not much else).

https://esbuild.github.io/content-types/#typescript


You IDE should check the types for you.


This might worked on solo projects but if you’re working with people, I’d highly recommend enforcing type checking of some sort. People will ignore the IDE error messages.


> People will ignore the IDE error messages.

Then they get caught in code review at least in any team I work.

No way I accept any unnecessary "disable lint" statement in a PR.

Also (of course, since it is default) the CI build system breaks if they commit and push without ignores, so no, trying to slide it past me doesn't work either.


It's not linting, it's typechecking which is slightly different. Linting won't catch type errors. All I'm recommending is to add a typecheck to the CI system so no one sneaks in a broken type (I couldn't recognize a broken type in a PR personally).


Yup. Vscode has built-in Typescript support so that does all the type checking as you go.


Typescript, esbuild and preact are hardly boring, since most JS dev don't even have tried it yet.

React is just starting to become "boring", and I mean that in the JS sense of the world. Because it's lifetime would be considered "modern" and any other language.


Wasn't esbuild released literally last year?


In JS terms, that's like a dinosaur.


Typescript, esbuild, and preact would have been described as shiny not very long ago. These things take time to mature.

I agree that the current JS ecosystem is fine if you don't get too far off into the weeds with obscure dependencies.


IMHO, JS is has more mature parts than any other language. It's fast, stable, portable, practical and for every problem you could imagine, there's an answer on Stack Overflow, immense community, easy to learn (while hard to master, like the English language). The problem is, the popularity also brings huge amount of immaturity. So, it also has more immature parts than every other language too! People keep adding new libraries, trying to promote them, and most of them are indeed beginners, because when most people start programming, they do learn JS mainly, or as an addition.

Yeah, JS has a very small standard library which exacerbates the problem but if you look at the amount of libraries that do what they do best and are stable, I guess no ecosystem is anywhere close.

Beginners should just follow the happy path, and it almost always works fine. People can use "create-react-app" or "express.js" or "lithtml"... But just learn the language too. I use next.js myself and am surprised how everything just works. I can't say the same for many C# frameworks (and from Microsoft nonetheless).


... happy path... Having come back to JS recently after years away I feel that typescript should be the recommended way of interacting with JS. It makes it much easier to write code with reduced bugs.


The often unmentioned killer feature part of js is that you can express tree data directly*:

person={ name: "frank", address:{ city: "Berlin ", zip:12345 } }

It's a different kind of "maturity" than discussed in the post, but a very important maturity nonetheless.

* (without TreeDataFactoryImplementation treeDataFactoryImplementation=TreeDataFactory.newTreeDataFactoryImplementation())


>The often unmentioned killer feature part of js is that you can express tree data directly

This is the case in almost all well-used programming languages. Calling it a "killer feature" is a bit of a stretch; it's more an expectation.


You are right. I was thinking of Java, C, C++, and C# but my knowledge about the last ones was outdated (long ago)

https://stackoverflow.com/questions/138600/initializing-a-st...

https://stackoverflow.com/questions/15501202/c-sharp-nested-...

IF you are happy with some constraints or the syntax exploding with every level of tree depth added: public Dictionary<string, Dictionary<string, string>> info = new Dictionary<string, Dictionary<string, string>> ....


You can define type aliases at the begin of the file to reduce verbosity, as example:

    using dic = System.Collections.Generic.Dictionary<string, string>;
Otherwise you can use an anonymous type:

    var person = new { name = "frank", address = new { city = "Berlin ", zip = 12345 } };
In this case you get a plain object, but all fields area read only.


Interesting and beautiful


I try not to use any libraries that were introduced less than 5-6 years ago. Thanks to this I don't experience much library churn and don't have to rewrite the same thing every few months. For example, I didn't pick up React until 2020. Let the kids play with their shiny toys if that's what they want.


I think this is a smart heuristic if you optimize for stability. Incidentally, you started to learn React when it's API's got drastically simplified over the previous class based approach. You joined at the right time so to speak.

But I want to add that play isn't just for kids. For me, it is an important part of my life and work. Deliberate, free play gets you in a different mode, it's fun and worth doing without some external reward. Does it have to be new, "shiny" toys? Not at all! That's the nice thing about it.


The title misses the point.

You can have a perfectly stable JS experience if you let go of the need to stay on top of the latest trends. I've done node.js since it came out and I stopped feeling like the author about 5 years ago. I've continued developed in js regularly but am generally "out of the loop" with regards to web framework trends etc. Apart from deprecations of request and moment and the occasional syntactic sugar, not much has changed in years now.

Just the other day I made a greenfield web project for the first time in a long time, took me about one intermittent day to get from 0 to "good enough" with a couple of views. typescript, hapi, and pug. It doesn't have to be complicated.

https://codeberg.org/3np/rimgu

(Not saying this is a perfect project and you may argue it falls under the "do x in 10 mins fallacy" but if you think JS projects have to be complicated and unstable - they don't have to)

Also, I find it unexpected hearing that comparison with Ruby. I've spent way too much time struggling with Ruby deprecations, buid systems, linters, and broken or undocumented web frameworks (Grape) that I think Python may be the one better comparison.

And really, which ecosystem with comparable legacy has a significantly better track-record of webdev stability? Java? .NET? PHP? Go? It's a mess everywhere.


All this complaining about churn is ignoring what the churn stems from. There's constant, incredible evolution in the JS ecosystem. Some examples :

* New syntax that makes JS so much more expressive than before, like arrow functions, spreads and null operators

* Typescript has made development so much better and reduces the need to unit test structure

* React was a paradigm shift when it came. React hooks is another paradigm shift, I've written code in the last few months that would have been so much harder to write and been much more buggy without hooks

I spend at most a few hours per month upgrading packages and dealing with churn. It's a small price to pay


Isn’t React slow, only able to manage tables of a few dozen rows before slowing down to hell, hence starting the trend of tables paginated by 10 rows only? Isn’t that the cost of hooks?


React doesn't have an inherent problem with larger tables, and there are quite a few libraries to virtualize long lists or tables if yours are very large and you need the performance.

React performance can be a bit tricky to handle if you don't understand how React rendering works and when React will render. But that's not really different from most things, performance is something that you often cannot abstract away entirely.


I've written code that would have been incredibly hard be made performant without React. With React, vittualizing rendering to only render visible elements is a breeze thanks to the inherent composability of react components, and now also hooks.

React is not the performance bottleneck, the DOM is


That isn’t just disagreeable, it’s measurably wrong. The DOM is insanely fast when you aren’t lazy, such as using query selectors.

https://jsbench.github.io/#b39045cacae8d8c4a3ec044e538533dc

A trillion unnecessary and never removed event listeners will also destroy your performance. Event listeners are an extra layer of abstraction that you can live without if you know what you are doing. That’s a big unlikely if.

React is not really a performance bottleneck either but it also certainly isn’t a performance benefit. This is that immaturity the article speaks to.


I am talking about DOM manipulation operations such as creating and updating elements. See my other comment.

React does not query the DOM at all (almost), so query speed is irrelevant


DOM operations are just a few common methods such as: appendChild, removeChild, setAttribute, getAttribute, removeAttribute, createElement, createTextNode. These were slow when injecting massive quantities of new nodes more than 12 years ago. Now they are fast.

If you are that concerned with speed then just produce everything in a document fragment and when ready inject the document fragment into the document. Bottleneck bypassed. React won't solve for that bottleneck because it is still JavaScript beholden to the DOM just the same.


how do you replace event listeners? attach all of them at the document root and wait for bubbling/capture? attach single event listeners somewhere and then dispatch manually? use onclick="..." attributes? or maybe are you referring to native functionality like actually using semantic elements and using links and forms for page actions (with a service worker I believe you can make a nojs website quite interactive even offline)

I believe I am not exactly "know what I am doing" at least when it comes to implementation, so I would enjoy some clarifications


Terms:

* Event - an asynchronous action, possibly but not necessarily the result of human or network interaction

* Handler - a function that executes instructions upon the event

* Listener - an abstraction layer to bind handlers to events using an allocation pool and not assignment. One handler may be provided to multiple listeners and one event may receive multiple listeners

* Callback - A function provided to a handler such that instructions not associated with the event are executed via reference

You can assign a handler directly via a DOM property:

    myNode.onclick = myHandler;
In this case there is no listener. There is a node, an event, and a handler only. The handler is implicitly provided an event object as its argument (if not explicitly specified), which in turn provides all the identity necessary for the event and node without further abstraction or external assistance. The node identity is `event.target` and the event identity is `event.type`.

The limitation with handler assignment is that only one handler may be simultaneously assigned. This is bad when your media/analytics team, who has no idea what they are doing, installs a bunch of third party spyware on your business site without permission that wants add a bunch of data tracking to every user interaction.

The benefits of handler assignment are: guaranteed garbage collection bound to the assigned DOM node (and more specifically the actual event if the event is reassigned a different handler), code simplicity (forced), no listeners.

A listener allows association of multiple handlers to a single event and/or reuse of a single handler to multiple listeners.

The problems with listeners is that they wildly complicate code and the respective handlers are difficult to garbage collect. As the given node is removed from the document the best practice is to manually call `removeEventListner` on each listener associated with the DOM node. Garbage collection is difficult for these handlers because there is no clear relationship between them and their corresponding events. The risk of not garbage collecting resources is that the application grows in memory with every event interaction, often unnecessarily duplicating allocations, until the application fails. Performance is also impacted in a logarithmic fashion as the stack size increases. This is called leakage.

Frameworks attempt to solve some of these problems with handler/listener allocation, but they aren't universally successful and it is challenging to measure how unsuccessful they are as it varies by instance.


  > React is not the performance bottleneck, the DOM is.
I think that's pushing the blame just a layer too deep. It's like saying that engines are not holding up hypersonic missile development, the thick atmosphere is.


No, it's the truth. Whether you use react or vanilla js, creating 10 000 complex element trees is going to take a lot of time due to the DOM recalculating layout and redrawing between every DOM operation.

React makes it easy to draw less through virtualization. Virtualization is very hard to implement in a non-declarative way


I can easily build a table in HTML with 70k cells (100 columns, 700 lines, it does happen, and users prefer that when getting an overview of their project), but in React, it takes 15s to render. Setting the innerHtml takes milliseconds.


Just use something like react-virtualized. Problem solved


it remains true that react is unable to use the DOM at its full performance regardless of virtualization.

part of it is that after all react is a library and not a compiler (which is good per se, I like that you could use react with only vanilla .js and .mjs files or even once big HTML file) which means that for the react runtime components are black boxes and cannot be statically analyzed nor statically optimized.

in the case of a table with 70k rows, even if the component only returned one jsx without any computation react would have to run the same diffing algorithms (this could be solved with a useMemo, but not always)


React does not seem fast in this benchmark https://krausest.github.io/js-framework-benchmark/2021/table...


When a language becomes stable, it also begins to lose popularity. (This is widely discussed).

Javascript is the only language that has continued to grow forever without becoming an "old" language in dev mindset.

One reason is the constant churn of tooling, another is the immaturity of everything, so every generation of devs have a place to add something.

Overall JS gains more than it loses.

This is similar to the concept that the first buggy language to capture mindshare will eventually fix its bugs and leave the initially more perfect competitors behind.


Well having a monopoly on the most popular and power programming platform of the planet, the web browser, will do that.

In fact, remove the browser monopoly, and give it to Visual Basic, and in 3 years, VB will be the most popular language of the world.


That’s the thing about JS. It’s popular because it was first and grew into a monopoly. The language itself is horrific. We are permanently stuck with a poorly designed language because it has momentum which can’t be overcome.


Worse is better, it still seems.


But all these improvements should mean productivity improvements. But my engineers still aren’t able after 18 months on a React project to churn screens like we did with Freemarker+jQuery (=with bare hands, technology-wise).

Every new tool should accelerate the pace, but JS doesn’t seem to deliver.


The main reason JavaScript is still "popular", is that you are more or less forced to use it if you are targeting web browsers. And since web developers had to spend a lot of time learning that crap, combined with that whole DevOps culture, they ended up wanting to use JavaScript on the backend as well. Which is such a bad idea it's difficult to explain even.

People are starting to realize that this whole JavaScript ecosystem was a huge mistake. The level of complexity a typical Node framework introduces, compared to the benefits you get from using it, is just silly. A typical web developer doesn't understand this fact and naturally feels stupid when trying to figure this thing out.

Some are moving back to PHP or Ruby, others forward using Go or Elixir or such. Even ASP.NET is simpler to work with than Node and friends, and that is telling a lot.


It is a lost cause to rationally try and sort out what if anything is chronically wrong with js, ruby, haskell, c (or any language of choice). They each have their pros and cons, and have evolved differently for different reasons. Since programming languages many times (seemingly) are like a dear spouse to its disciples such discussions generally devolve into endless and meaningless comparisons, if not worse.

The article obviously panders to ruby sentiments, and the javascript experience can obviously be frustrating to that community, as might ruby to a mainly javascript developer. Might we just leave it at that?


I think the big difference with JS is that if you're doing just about anything in Web Dev these days, you MUST use JS (with a few exceptions).

Don't like PHP? Try Python. Why not Go, Scala or Rust? Don't like Ruby? Move to Elixir (no really, do it! you won't regret it)

But with JS you're stuck with JS - at least Typescript makes things a bit more sane.

So until the browser monopoly ends and something supplants JS as one of the only ways to make a dynamic website, it will have to take the heat.

The best experience I've encountered is with LiveView in the Elixir/Phoenix world. It still needs JS for the plumbing (websockets) but I no longer have to write JS. Happy days!


I can understand new libraries being crappy, it takes time to get good and that's why you should pick well established libraries. True, the hype machine is huge in the js world and the superstars in it are better marketers on twitter than coders.

I'm not going to touch anything graphql related for at least 5 more years and hopefully I will never have to touch it. React became decent last year when next started being mature enough.

What I don't like is all the transpiling and new language features getting to js. The single worst decision was to swap require for import. I don't care how much better the new model is, it broke too much stuff and I feel pain at least once a week because of that crap.

Frankly, that's a nightmare and I think it will be years before it's decent to use - or maybe we'll need deno to get there.

I swapped js with rust (+rocket) for all my personal projects and it's been nice - but I'm still stuck with js on a few projects where I'm collaborating with other developers who are not going to realistically learn rust.


Complexity and instability in the JS ecosystem is a hot button for me, so it's hard not to be drawn into vehement agreement.

I've been doing a little work recently with htmx[0] and it's a breath of fresh air. But then, I'm at the point in my career where "cool new tech" is much less interesting for its own sake than it used to be when I was younger. I'm drawn far more to elegant, understandable, productive simplicity these days.

I think that hints at the reason we have these endless debates - not just about JS but about $(your-favourite-tech). Software development is a socio-technical endeavour. We put all the focus on the technical part, and by comparison, rarely consider the social aspect.

DHH is one of the few I've heard actually refer to this, on the corecursive podcast [1]. In discussing static typing vs dynamic, his point is the latter suits his brain. But that he understands and accepts static typing suits others, and that's fine.

So I get that, for some, the JS ecosystem is dynamic and interesting; stimulating; exhilarating even. For others, it's an unstable quicksand that gets in the way of doing something useful.

[0]: https://htmx.org/

[1]: https://corecursive.com/045-david-heinemeier-hansson-softwar...


The ecosystem of JavaScript frameworks is almost unbelievably unstable.

Popularity isn't a measure of quality of course, but if you're going to make a statement like "JavaScript frameworks are almost unbelievably unstable" you probably ought to cite some sort of evidence for that because reality is very much against you.

There are about 10,000,000 React websites[1] compared to 95,000 Rails[2] websites.

There are 325,000,000 websites that use JS[3]

I mean, JS can't be that bad in the face of those numbers, can it? JS developers aren't all getting it wrong are they?

[1] https://trends.builtwith.com/websitelist/React

[2] https://trends.builtwith.com/websitelist/Ruby

[3] https://trends.builtwith.com/javascript/traffic/Entire-Inter...


I don't understand how the numbers you've posted here support your argument. You said it yourself "Popularity isn't a measure of quality" and then go on to imply that it does.


I'm not suggesting JS is particularly high quality; I'm just saying that it's not completely broken. There's a middle-ground where it can be both good enough quality to be usable, and good enough to not be considered broken.

Given the fact JS is used by hundreds of thousands of developers it is obviously not totally broken, so if you're going to say it is you need some very strong evidence to back that up.

Half the time when I see "JS is so broken!" posts they're by Ruby devs. I can't help wonder why they're all so keen to move away from Ruby.


I know we're not supposed to say "did you read the article" around here but there was a fair amount of nuance in it and you don't sound like you disagree with it in any huge sense.

> Half the time when I see "JS is so broken!" posts they're by Ruby devs. I can't help wonder why they're all so keen to move away from Ruby.

That's an interesting assumption. I would have started from the position that javascript is a mainly a front-end solution so one wouldn't "move away from Ruby" to use it because you would still use Ruby on the back end.


That's like saying there are X million humans driving therefore humans can't be that bad at driving. There is really not much of a connection between those dots


Humans are amazing at driving. Given how many billions of miles are driven every day, the number of accidents is mind-bogglingly tiny. You'd think there would be many, many more.

That is quite a good analogy to JS actually.


> From backend ORMs and headless APIs to frontend site generators, package managers, and build tools—it's a miracle any of it actually works properly in production!

I think the issue is clear from this first sentence. Why are there any of these things in javascript?

The marvel is that in 2021 such a sentence can be written -- that these things are immature seems both obvious and to miss the point.


Why should they not be?


Javascript for most of its life was essentially a DSL for the browser. That, in 2021, we're talking about build tools written in it, should give us pause for thought.

> "Why are my devops tools written in this browser DSL immature?"

Well, where to begin?


I'm not aware of any ops tooling that's built in JavaScript. (I'm sure it exists, but it's not popular.) When the article is referring to build tools, they likely mean transpilation/bundling systems like Babel and Webpack, which are fairly reasonable uses of JavaScript.


So engineers only have one language to absolutely master.

This really hit home: Trying to recruit a Java + SpringBoot + Angular engineer is 1 order of magnitude harder than a NodeJS + Angular engineer.


Languages aren't hard to learn once you've got 1-2 under your belt.

FWIW I wouldn't consider myself to have "absolute mastery" in any language, there are some I'm more comfortable with than others but even when I'm not I can still be productive.


They might not be hard to learn, but it's still a considerable mental overhead to switch between writing JS on the frontend and anything but JS on the backend. I frequently mix up the simplest things, like len(list) vs list.length, or how that you can't use obj.property on Python dicts, or list.append() vs array.push(), etc. And then you might have a great tooling library in one ecosystem (like lodash in JS) and try to replicate the things in your backend language. That sort of context-switching simply isn't worth it in my opinion.


Languages are not that time consuming to learn, it is the development environment, frameworks, libraries, community, best practices, tooling etc that takes a lot of time.


> So engineers only have one language to absolutely master.

I'm always amazed at the reluctance of developers to learn and use multiple languages. To use an old analogy: they're like carpenters who are unwilling to learn how to use a saw because they have a perfectly good hammer.


Still learning a language (or a carpentry tool for the matter) is a cost no matter how easy.

It would be great if we could have a unicorn language that can do it all optimally - or at least adequately. Then we can fully focus and master that one language.

Nevertheless I think most will agree that JavaScript isn’t that language.


Why not generalise SQL with classes, loops (, etc.) and truly single-language the world? And an SQL configuration language ("UPDATE aws.ec2.config ...") ?

Typescript is a testament to the extreme amount of work needed to normalize a scrappy browser-lang for robust use.

The issue is precisely that a community of "SQL developers" are not going to build you robust tools, merely by having generalised SQL. And likewise, a community of browser developers aren't going to either.

Single-languaging down to effectively a DSL produces a particular type of community (, language, domain of competence, ...), which is exactly what OP is complaining about.


Instead of only getting one shitty JavaScript stack, you get two. Great.


Big part of the issue is that it's quite hard for newbies to tell what is JS and what is the framework and what is a web standard.


A part of this is that the tooling mostly depends on huge trees of dependencies.

If top level tools devs interacted with bundled more of their deps things might be less likely to break, at the cost of a bigger node_modules folder.

Right now you occasionally run into situations where Webpack or ESLint stops working right because is-even released a bad patch update.


Does anyone else think it’s weird that trivial syntax/typesystem frameworks get very popular whereas things that actually move tech forward, like new apis/webgpu dont get much hype? Maybe it just seems this way. I mean how many ways can we come up with to watch ppl struggle to build 2D form applications?


the way to deal with the immaturity of javascript is to build instead off mature technologies like hypermedia

Hotwire and htmx do this


Best career choice I did in my life was quitting frontend dev, I was in deep as frontend architect and similar senior positions. I still need to do some pure JavaScript frontend occasionally and every time it is even more mad than before. Always reminds me what hellhole I managed to escape.


Not saying you're wrong - but a few examples or stories would help sell this idea.


It's was my take in 2015, when saying it then got you bashed to death.

Now you can say it, since people have been burnt enough to admit it, but ironically it's actually less true.

Yes, the JS language is always hackish. The stdlib sucks and the ecosystem is a Jenga tower. A lot of JS projects are still what I call "disposable code bases".

But.

Modern JS is tolerable. Functions are now decent, you have let/const, map/filter... There are even some nice things:

• spread and destructuring, and they play well with the limited data structures.

• simplest async paradigm ever: immediate schedule, and returns a Future, may attach a callback or prefix with await.

• concise arrow functions.

• ? and ?? operators. I actually miss them in Python.

Tooling has improved tenfold:

• VSCode gives you good code intelligence out of the box.

• any build tool will solve imports, scoping, "this" weirdness, browser compat, etc.

• new gen builders, such as ViteJS (or anything based on rollup/esbuild), are fast, reliable, and have sane default. No more webpack trouble.

• new gen packagers, such as pnpm, are fast, reliable, and save a ton of disk space. No more "takes 10 minutes, download the entire internet 3 times".

• with VueJS (SPA), htmx (ajaxify Django, Rails, Laravel...) and petite-vue (progressive enhancement), front end dev is almost fun. And light.

• Typescript.

Now, I still avoid JS if I can. I don't like having to google simple things like type coercion or how to left trim a string.

As soon as I can go Python, I do so. It's hard to beat Django or FastApi for the web, Typer for scripting, pandas for data analysis, pytest and robotframework for testing, or just the stdlib/pypi.org for pretty much everything. And with shiv and nuitka, deployment is now on a different level.

But when I have to use JS, I don't dread it anymore.


And I think the article is largely correct even though I don't dread developing Javascript-based applications.

One of our Nuxt applications with default build configuration sometimes builds successfully and sometimes fails miserably for reasons not understood. So we just run the process until it succeeds. I would never tolerate this in Python or take it as lightly as I do here, but like a frog in hot water I've been conditioned to almost expect it or at least not get too bothered by it.

I think Javascript the language is fine. But the rest of ecosystem feels enormously creative, myopic and too often fragile.


The thing with Javascript is that it sucks so bad that there are what a dozen or so languages built on top of it that get transpiled to JS to run in a browser or on V8. It sucked so bad that nobody really wanted to use it, they'd rather build a compiler and write in something else and tranpile into JS. How can a language be "good" when there are so many attempts that take such effort just trying to avoid it.


Note I never said it was good.

Half of the popular projects around JS are indeed created to workaround its deficiencies, or the JS DOM API limitations.

But working with JS, thanks to those efforts, is now much more agreeable. And the language itself has evolved in the right direction.


I agree with this 1000%.





Consider applying for YC's Summer 2025 batch! Applications are open till May 13

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: