JavaScript—it was never meant to be that way.
JavaScript. Nowadays, it is everywhere. And when I say everywhere, take it literally. From the classical use case in the browser, over the server-side logic until you reach the low-level section with embedded devices. And like no other language, it is really polarizing. Some people who hate it, and people who don't do anything else all day.
Let's do a quick history lesson
Everything started at Netscape, the first browser that ever existed. They at some point decided that it would be cool to have some way to execute logic in the browser. At that time, Java was the hottest shit, so let's do something like that.
And that's how in 1995 LiveScript was born, which was quickly renamed in December to JavaScript. The name, that still confuses some people nowadays, implicates that it is somewhat like Java. And that's everything but true. Besides the C-like syntax, it's not really comparable.
Over the years JavaScript has changed, the ECMAScript-Standards came. With Node.js coming out in 2009 the hype was completed. Learn one language, that you can use in the browser and on the server. Full Stack isn't so hard anymore. At least what most people think.
So, why is it not meant to be?
JavaScript was not built to handle stuff it does nowadays. There are multiple fuckups that are revealed (and you can read about) anywhere all over the internet.
The thing is that the language that was designed so quickly and got so popular, so it is nothing you just change overnight. Every new feature or behavior must be backwards-compatible. Of course, there is new stuff coming, but the essential flaws still exist.
Let's take for example the single threading, of course you can do things in the background, but you simply have no control about it. For initial pages and the use cases this was totally fine, also keeping in mind resources were more limited back in the days. With new generations of hardware coming out, it seems like the priority has changed. Everyone has a beefy machine, and even phones are mighty computers in your pocket. But that's only half of the truth. As with more power on devices, there are of course more things people try to implement.
We shift into a web-first approach where you just develop for the web platform and run it basically everywhere. VS Code, Slack, MS Teams are excellent examples that this is not fiction but reality for everyday use.
And these applications run to problems with the limitations almost every day, instead of addressing the actual problem (which is the language itself) we add new technologies on top of the problem.
As time continues, there were plenty of approaches from different people, all having a transpile part. So, basically translating your language to JavaScript. Most of them fixed parts of the things, by adding types, more consistent results and easier maintainability. That there are so many of them, already indicates an issue.
But there is TypeScript, WebAssembly and many more now! — Almost a solution, somewhat.
Let's take WebAssembly. Compile your code for the browser and gain performance and reuse libraries. That sounds great, and definitely has some neat use cases. Nevertheless, you still need the JavaScript glue, and you have strict limitations when it comes to the DOM. So, you basically don't get rid of the scripting language for the basic concern.
Just another technology built to resolve difficulties that can't be entirely fixed this way. And the intention behind it is certainly not to replace it, but fixing the weak parts, by adding an alternative. As it seems, it works even for Photoshop! This is of course a great thing and already an addition that makes things easier.
WASM is also already superfast, especially compared to JavaScript.
Most people nowadays use TypeScript, or have previously used Dart, CoffeeScript etc.; these are all languages that cant exist without JavaScript. You may write your code in a safe and predictable manner, but at the end it is all just plain JavaScript. So, it seems like it is a lot better, but the essential problem, the language, of course, remains. While this works most of the time, I also had some weird headaches with generated JavaScript code from the TypeScript compiler, for example.
But one thing is in common for all: They increase complexity at the end of the day.
More frameworks to the rescue
The DOM (still the main use case for most JavaScript out there) is pretty optimized by default. A thing that really is no common knowledge anymore. People just assume it is bad because there are so many frameworks out there. Many of them utilize Virtual DOM, abstraction layers on top of abstraction layers.
Most common thing: Combining all DOM changes into one instruction, to “optimize” the amount of changes. The truth is: It doesn't matter. JavaScript is blocking the rendering. Which means, no matter how many changes you do, it will wait for them and then take that as base for rendering your page. Ats also the reason WebAssembly etc. don't have access to the DOM. It would simply be not controllable, since you can also have threads etc. there, which would lead to completely random results at the end.
Most of the frameworks address issues that don't exist or are just caused by the language (or another framework/library). So again, instead of resolving the actual issue, we just add another layer of complexity.
Don't get me wrong, sometimes a framework just makes your life a lot easier, but most of the internals and so on are just so bloated and stuffed with unnecessary over-engineering. This results in slower performance and new difficulties, as large bundle sizes, which are then optimized using another layer of abstraction and tooling.
What really grinds my gears here is that JavaScript tends to be a complete mess when the codebase grows. At some point, you just can't work without a framework anymore. Whether you choose one of the big three Vue, React or Angular. At the end of the day, you have increased complexity and more things to take care of.
And there are definitely languages out there suited better for this large projects.
At the early days of the web, JavaScript was not suitable (and not intended) to render your entire application in the browser. But as clients become more and more powerful, why not moving the compute capacity from your data centers (or the cloud) to the client. It totally makes sense, costwise, and also leads to a better user experience. These giant projects and problems you face are simply things that were not there when JavaScript was made. Of course there is a lot of new stuff coming, trying to fix it. Just take a look at Project Fugu, that already brought us so many cool new features, all with a JavaScript API.
The never-ending story with the ecosystem
JavaScript ecosystem is great at changing, adding new stuff that already existed and attempting to resolve concerns that exist because of “solutions” other devs built. It's crazy if you think about it.
Many people outside the JavaScript bubble often joke about package craziness. Just take the is-odd package for example. As supply chain attacks in this ecosystem are totally normal nowadays or upstream packages being compromised. This is the cherry on top of it all, making it even more unnecessary complex and more obscure.
Finally, the update cycles here are just freaking crazy. This has not directly to do with JavaScript itself, of course. But at the end you are not just using a language, but also the surrounding ecosystem.
Adding a “native” alternative would be the real solution
The best thing to do would be to add another language out there, or just build something like Java Byte code, an intermediate language. Something that can be used like WebAssembly, just without the whole JavaScript stuff.
Of course, adding more complexity for simple stuff would be a terrible idea. At the end, this is what makes the web so charming and powerful. That would be a lot easier to use. But let's see where WebAssembly will take us, hopefully in a better world with more optimization possible.
This is not a thing that will happen overnight, but one can dream! ;) There are definitely more than enough reason that it would make sense to do it.
My conclusion
I have to work with JavaScript, TypeScript, and browser stuff almost every day. Always loved the simplicity compared to desktop native development. You should always take the latest and greatest stuff in the JavaScript ecosystem with a grain of salt anyway. Most things are already pretty good without optimizing things, that don't need to be. Maybe some day there will be a complete, natively supported alternative to JavaScript.
After all, it is love and hate at the same time for me. It is a really universal language, but you sacrifice control, performance, and a lot of brain cells to take advantage of it.