Friday, February 12, 2016

A farewell to Node.js ... for now

It's tough. Choices have to be made and decision taken.

After spending years experimenting (and even professionally working) with Node.js I think it's time to say farewell and thank for all the fish.

Why?

There's several reasons but the main for me are:

Asynchronous IO is tough. Really tough. Callbacks, Promises, Async/Await all that stuff. Sure, Async/Await will make this easier but under the bonnet it will still be async. I think the cause of this is that we think sequentially - do this, do that do something else. Not do this for user1, do this for user2, do this for user3, do that for user1, do that for user2 ... The fact that we serve several users at a time doesn't have to be reminded to us all the time.

Debugging and testing is pain with callbacks. As async functions are normally executed in their separate threads you lose continuity when your functions resumes. It's hard to track down where you'd been before the callback got called. And simulate callbacks in unit tests doesn't help either.

Dependency management. NPM everywhere. Node.js doesn't have its own packaging, module system and relies on NPM to do the hard work. Problem with NPM is, that if package A depends on package B and that depends on package C it's all nested and not reused. That means, you can end up with hundreds of packages C in your project. I still remember my Ghost blog project. It downloaded 500MB of NPM modules just to run!

Spartan core libraries. Node has very limited number of standard functions. It means that even for simple tasks like working with dates you have to turn to libraries like moment.js. Most of the stuff you can find in standard libraries in other languages needs to added as a dependency in Node. So you always facing decisions like `lib1 has these features but lacks some other` so you mix and match all the time to get basic stuff done.

No opinion. We all know that today's patterns and best practices are tomorrow's anti-patters. But this cycle is massively accelerated in the Node.js world. Grunt, Gulp, NPM. This is rapidly changing and there's no sign of consolidation. It's hard to operate in a world where tools are discontinued on a daily basis (with no replacement). Node needs something that would define and guarantee the basics so you can focus on programming and not worry if your code will be buildable in a year's time.

No explicit types. We can probably debate this for ages but as there's no way to enforce types (at least optionally) it's very hard to define contracts between libraries and their users. There's nothing that would warn you that a return value can't be assign to your variable. Or calling a function isn't possible because of incompatible types. That puts extra pressure on library authors to well document their code so the types are documented, somehow.

To sum it up. On front-end I'm left with no choice - it has to be JavaScript or transpiled JavaScript. For backend though, I stick to something else.

No comments: