Yet Another NodeJS Experience
I have not been a huge fan of Node but I recently completed a fair-sized greenfield project and thought I’d write my experiences down.
TL;DR Node is not all that bad in some ways, still a bit scary 👻.
The major players in the stack were
mongoose. I had to use Node 6.8.1 so I also brought in
yield and avoid using callbacks. In the immediate future I will upgrade and switch to
async/await. I used
sinon for testing.
I’m not going to write about the reasons why I ended up with this stack but instead focus on what my fears were around Node and what happened with each of them.
Scary Stuff 😨
So for my project I tried choosing the oldest and most mature dependencies, and avoid language-level libraries like
lodash. Before reaching production
mongoose pushed a minor update that introduced a warning that the way I was connecting to mongo was going to break soon. So I fixed that and it broke my tests, so I had to submit PRs to
mockgoose so my tests would pass. It seemed like like avoiding dependencies was already the right approach, and my fears here were grounded in reality.
for in loop,
for of loop with modern Node, and
TypeScript was also tried, and it was nice to have types, but it adds a build pipeline to the backend which seems really strange so I decided to skip it. Also something about writing a language that compiles to another language which is the one that is really running is kind of scary.
Node has kind of a unique runtime that automatically kicks off IO concurrently and then finds other bits of the code to run in the meantime. This sounds desirable until the realization hits that most of the time in HTTP servers things happen sequentially and callbacks/Promises just create a layer of errors and confusion.
I managed to avoid most of this with
co (more on that later) but I still used Promises to do a few things concurrently which went well. Occasionally I got stacktraces that didn’t reveal the true calling code, and some errors didn’t propagate in the way I thought they would. Those mostly came from dependencies that I was using that I assumed worked sanely. Another reason to avoid them!
Happy Stuff 😅
Simplicity is Possible
Since I restricted myself to a subset of the language, Node feels a lot like Go. Writing simple functions that call other functions and using parameters instead of class inheritance is pretty clean feeling and makes for easy reading code.
Also it’s really easy to use functional programming with built-in
reduce, and arrow functions. Using these techniques along with a good idea of how to layout the project produced a very clean and readable implementation.
Async & Await
With the introduction of procedural code style using
async/await, tests and REST endpoints can now avoid almost all use of callbacks and Promises. Occasional use is still recommended when wanting concurrency, but I found Node to be almost unusable without this feature (or simulated with generators and
Tests and Server Start and Restart Instantly
Python, Ruby, and Go users may take this for granted but after using Grails/Spring Boot for years, this is the most amazing productivity boost ever.
So with all of that considered… yes Node is pretty ok. I could see myself working in it more but I am going to try to convince all the Noders I know to go the way of TJ Holowaychuk and switch to Go.
Thanks for reading!