> There is an interesting amount of energy put into making asynchronous code read synchronously in situations where asynchronous code provides no benefit.
I see many new / intermediate people trying to do this. They want to make everything asynchronous when it does make sense to. You want asynchronous when you're accessing an external resources or for something low running (in which case yields / multiple asynchronous calls are necessary to free up the thread for GUI rendering if we're talking web browser here).
I do not like the new async / await syntax. Some days I think I'm alone in this but synchronous and asynchronous are two very different use cases and I think allowing both to be represented the same way can be highly confusing.
> The dependency tree of any one project tends to be incomprehensibly sprawling
This is entirely developers faults. NPM gives you A TON of rope to hang yourself with and every project I jump into people use libraries without considering to their dependencies and end up with a tree of over 3,000 dependencies. It's absolute madness!
> Runtime version numbering is... weird
Semantic versioning has been around for quite some time. I used it when I did Java and C# development; is it really that weird? Is there something about it that's weird?
> Don't even get me started on the interplay of Gulp, Grunt, Webpack and NPM.
NPM is kinda necessary for dependency resolution but beyond that gulp, grunt and webpack are all replaceable with simple scripts. It's actually one of the best and worst things about the JavaScript ecosystem: you can make your build work and behave in any way you want but you have to write the code or learn one of many build systems to do this. In other spaces, like Java, you typically just have ant and mavin and no one bothers with anything else.