Web programming is going fairly javascript crazy at the moment, and for good reason. As the only universally supporting in-browser scripting language it has a monopoly in its niche few other languages can match, and the popularity and increasing demands placed on it have led to some truly impressive optimisation work by highly motivated and well resourced organisations.
As the complexity of the client side of the web application equation has increased, the desire to be able to share code (and programming load) between the client and server has become increasingly desirable, leading directly to server-side offerings such as Node.js (not the first server-side JS, but certainly the first to really gain traction).
A number of serious issues still remain in the path of serious javascript adoption. Some are merely a matter of time, others are so endemic now it seems difficult to imagine how they might be overcome.
Unlike most mainstream modern languages, Javascript suffers from an almost non-existent standard library. This lack was less obvious when we were just using it to update elements in a browser window, but with developers replacing entire stacks with JS code it is reaching a critical stage. While a wide range of developers are providing various bits of commonly-used functionality, their implementations differ dramatically and often overlap. Perhaps a real standard might emerge over time but at this point it doesn't look hopeful.
Similarly the language is suffering from a lack of standardisation across basic patterns. Even something as simple as creating an object is rife with debate. Install any 3 node modules and open them up and you'll find three completely different approaches to defining objects (and inheritance or mixins per the authors preference). In and of itself this isn't an issue as long as the interface is stable, however it leads to a much larger required body of knowledge. If I choose to inherit/extend a given class/object, I need to understand the particular method the developer has used for it, as well as the appropriate method of inheriting/extending it.
This gets even worse when it comes to things like singletons, modules, events etc. CommonJS are trying but even there the results have often been complex and difficult to understand as simple solutions are stymied by the client/server/sync/async mix.
Finally there is the async issue. In essence, Javascript is not an async language. It does not offer any of the standard features of languages designed for asynchronous operation such as continuations, co-routines, promises, or even threads. Some of these have been hacked on in various ways (promises/futures and WebWorkers for example) but again the enormous diversity of approaches has created a huge learning problem for a developer. Some asynchronous functions support event broadcast, others defers, still others continuation-calling style. Try to use the wrong pair of async libraries and you're left juggling two different promise implementations, plus handing callbacks off into what passes for the node stdlib.
A number of other popular languages suffer the same lack of async support, but almost none of them are used almost exclusively in an asynchronous fashion. All browser work is async, and if you use NodeJS pretty much everything you do is async. It turns into a morass of callbacks.
This is a serious problem. As it stands, even with nice simple synchronous server approaches we as an industry suck at producing robust, readable code. Add in an unavoidable layer of what genuinely amounts to bullshit (it's not *necessary*, we have demonstrated you can do async without callbacks everywhere) and we're faced with a programming nightmare - when a PHP process hangs doing something stupid, one client is affected. When a node.js callback graph does the same thing, the entire server instance grinds to a halt. Don't even get me started on the stack traces that result.
Worst of all, it seems there is genuinely no solution. JS is a shit language not because of the language but because it does not match the problem space well (anymore), yet it is the only option - nobody has successfully introduced a second language into the browser stack, not ever, and they have tried.
Various courageous people are attempting to deal with some of these issues. CoffeeScript is a language transform that has a lot going for it - not the least of which is that it attempts to reduce the number of different ways you can do classes and prototypes to just two - but the stdlib remains empty, tool support is still abysmal and it offers no solution to the callback problem. Various overlays trying to "fix" the callback issue are failing hard, just the same as they did for python - it seems you just cannot put this stuff in later, it has to go in on day one otherwise you can't wrap enough of the other shit the coder has to work with to be useful.
Perhaps the most interesting concept thus far has been simply to throw hands in air on the server-side and run a pool of WebWorker threads just like python, rails etc do now and offer a purely sync form of web dev for the most part, with the developer able to occasionally foray into async at the front when they need to write a chat client or stream a file. At this point, this approach in combination with CoffeeScript looks like the only real way that server-side JS is going to be able to compete with the existing platforms in code maintainability and ease of construction.
I suppose it's too much to ask for a miracle, some kind of new language shoulder-barged in by Google that offers a nice clean syntax with native async, the equivalent of PEP-8 and a solid standard library.
Yeah, that's what I thought too :(