My issue with JS (particularly but not exclusively server-side) is less that it has some weird aspects and more that its built-in functionality/standard library is incredibly barebones in many respects. IMO that’s the main reason why it’s considered normal in the JS world for a project to pull in hundreds/thousands of largely un-vettable dependencies.
Knowledge transfer, context switching, the stuff you already know. But there's also an interesting non-JS reason that's gotten forgotten because the serverside landscape has changed so much since the early 2010s. Node very heavily popularized single-threaded asynchronous request handling (ie, not starting up a thread for every request that came into the server).
Of course there is nothing about Javascript that means it specifically as a language is essential for that pattern, but I remember hearing talks from Netflix employees and industry advocates about how much Node had improved their performance; I remember industry people coming to my college and talking about single-threaded serverside code and saying "you all need to check Node out."
And there are downsides to asynchronous code (callback hell was the obvious downside that got brought up a lot before `async` or even promises had arrived in the language) -- but I remember among especially younger serverside developers this trend of people saying, "Node is just faster. That's why you use it, because it's just straight-up more performant than what you're currently doing." And I understand serverside devs from other languages can at this point jump in and say that it's not, that the single-threaded model is possible in other languages, that there are downsides to the single-threaded model, that Node doesn't do it well, whatever. I'm not arguing the point, I'm just describing the cultural shift I saw.
All of the conversations about sharing code happened too, but I remember having conversations where people talked to me about jumping to Node specifically because Express was single-threaded and because it could handle more concurrent requests than other popular server architectures that they were familiar with. And I suspect that it gave the ecosystem a lot of momentum.
Node's original purpose was in part an experiment to see if single-threaded async request handling would be able to handle large numbers of simultaneous requests. My somewhat-limited memory of the conversations that were taking place back then is that running the same language clientside and serverside was just the icing on the cake. The big reason people were excited was because Node was single-threaded.
When Node started to become a thing, Java and C# has already been doing multi-threaded web servers for about a decade.
Oh, and C# already had support for async programming too!
Node become popular in part because Silicon Valley just doesn't seem to be aware of anything that exists outside it.
Node was single-threaded async, not multi-threaded. The entire point was to not spin up multiple threads and to rely on the event loop instead.
> Oh, and C# already had support for async programming too! Node become popular in part because Silicon Valley just doesn't seem to be aware of anything that exists outside it.
> And I understand serverside devs from other languages can at this point jump in and say that it's not, that the single-threaded model is possible in other languages, that there are downsides to the single-threaded model, that Node doesn't do it well, whatever. I'm not arguing the point, I'm just describing the cultural shift I saw.
Right or wrong, you can go back and look at forum posts even only 6, 7 years ago and you'll see people asking about single-threaded performance and asking how Node manages to scale if it's single-threaded. A lot of developers at that time got introduced to single-threaded event-based asynchronous server programming through Node.
I'm not telling you that Node should have won, I'm telling you one of the reasons why it happened to win. Here's Dahl's original slides presenting Node in 2009: https://s3.amazonaws.com/four.livejournal/20091117/jsconf.pd...
Immediately the first thing he's talking about is not unity between the front-end and backend language or sharing code. It's "I/O needs to be done differently." That's what people were talking about back then.
What's interesting about this talk is that Ryan doesn't even mention Javascript at all (other than briefly to say that NodeJS is built on it) until nearly 13 minutes into the presentation. And it's clear that he's using Javascript as a means to an end -- he's going with Javascript largely just because Javascript by default has a single threaded event loop that every JS programmer had to learn to work with it.
So he brings up going with JS because JS programmers are used to callbacks already -- and then roughly 2 minutes later he immediately moves back to talking about I/O and request handling again. Very little of his presentation is about Javascript beyond an aside of "JS already does this and JS programmers are used to it, so we might as well go with that and try to copy JS conventions." He almost spends more time talking about common SQL libraries than he spends talking about JS.
I agree using plain JS anywhere is not a good idea, but Typescript (or js with ts annotations) is often ignored when it does a very good job of catching most of these issues, while offering a very flexible type system in a more mainstream paradigm
- Error handling is onerous; I write a lot of functions where most of the lines are just checking for and returning `err`
- No anonymous structs, and it’s really awkward to define structs inline
- Dealing with collections is really verbose; I guess since generics dropped I could handle this in userland, but it’s not idiomatic
etc etc. No language is perfect!
I make heavy use of map[string]any vs structs. I also find the right balance of checking err vs just making it _
JS has also had a lot of its "mistakes" fixed since 1995. It does so in a backwards compatible way and it isn't always obvious how much progress has been made, but it has never been a static unchanging, "unfixed" language.
(Personally, I'd much rather work with JS on the backend than golang. Golang looks to me like a throwback to the 1970s that misses good language design ideas from the 1990s. I understand some of why it has become popular, but there's so much bad design in that language that upsets my nausea.)
You choose against a language because of code that any sane person, which I hope includes yourself, would never write intentionally?
Weird flex, but ok.
Reusing code, tooling, training is meaningful.
---
Every language (Java, Ruby, Go, Bash, whatever) has quirks. JS may have more than others, but it's not alone.
I'll probably get flamed for saying this, but having all objects be hash maps that can be extended or edited at any point and be simultaneously dumpable and loadable into JSON with one line was an unfathomably big brained move. Being able to just use the data you get from various sources instead of having to create an ad-hoc struct/object that perfectly matches all types and values (and ofc crashes immediately if a change is made on the other end) is so underrated. That's not even mentioning the native async support.