Where to start with Node.js as a Java developer in 2017

Recently a friend of mine who is a veteran Java developer was asking me about Node.js development. He tried to do some Node development 3 or 4 years ago, and got frustrated with the lack of tools and Javascript callback hell. I tried to tell him that things have changed greatly since then, but found myself not able to formulate a good response in the moment. He had also read “How It Feels To Learn Javascript in 2016”, which is really funny, but isn’t exactly a vote of confidence to try Node again!

Shortly after, I came across “Why I Struggle With Node” by Graham Cox. It’s a great post about why he loves Node.js, but gets frustrated with its ecosystem and prefers that of Java.

Having been a Java developer for 7 years before switching to do mostly Javascript development, I can say that I agree with many of Graham’s sentiments. The Java ecosystem is much more mature and the tools are great. There are many things I miss. But I don’t get frustrated with Javascript’s tooling as much. I actually find the Javascript ecosystem and its tools invigorating, as long as you know where to start…

The post made me think of my conversation with my friend. I linked to Graham’s post as a starting point, added some additional thoughts and sent them to my friend to give him a place to start with Node again. After I wrote it up, I thought it might be useful to other Java developers who haven’t taken the dive into Node.js and would like to, but might be intimidated or not know where to start.

If you’re in that boat, I suggest you first read Graham’s post. It has a great list of tools to start with that translate well into front end code too.

After you read that post, here are my notes and addons that I think might be helpful if you are coming into Node development from Java in the beginning of 2017:

Learning Javascript

If you don’t already have a good grasp on the Javascript language, or consider yourself just good enough to be dangerous, I found “Basic Javascript for the Impatient Programmer” to be particularly useful in improving my understanding of the language. There’s tons of great books as well out there that you can easily find.

Also, before you dive into creating a full app or start setting up tools, learn the Promise API and use it from the start in your code. It will make your code easier to reason about, and will make your life much more pleasant once you get past the initial learning curve. If you can, use the Bluebird library for Promises. It has lots of great extras on top of the native implementation, and rumor has it that it’s even faster.

Builds

Like Graham, I use Grunt for building, too. I haven’t tried Gulp, I’m sure it’s great, but I’ve used Grunt for a while and have found it effective. Though, like Graham, I do miss the fact that Maven takes care of a lot of the gruntwork (ha ha!) for you. For my team’s apps, we have separate Grunt tasks and configurations for building front end and back end code since folder structures are different.

Transpilers

I don’t use Babel. If I’m being honest, the whole transpiler thing is a mystery to me. I kinda get it: You want to use new features in the language, especially in a browser environment that adapts rather slowly. But if you’re writing production code that needs to be supported by a team with varying levels of Javascript knowledge, it seems to add unnecessary complexity. It’s hard enough keeping up with Javascript, let alone when you do source to source compiling. It will also make your toolchain a lot easier to configure, and your debugging a lot more straightforward.

Code Coverage

This is mentioned in the post but I thought I’d provide what I’ve used: Istanbul through Grunt. It’s nice and simple and does the job well.

Logging

Graham mentions that Node logging isn’t as nice as what he’s used to in Java. That’s true, but I’ve used Winston quite effectively in production apps.

Debugging

Graham is right, debugging in Node is hard. I attribute some of that to it’s asynchronous nature, though.

I’ve used node-debug effectively as a debugger. It’s quite nice, but a real pain to setup. But, if I’m being honest again, usually I try to use Winston (mentioned above) to put some nice low-level logging statements in place so I can debug with those, then turn logging levels up and down as needed. Sometimes those low level statements help when you’d least expect it.

Application Wiring

When I first started with Node, we were using a dependency injection framework in Node since my team was used to using Spring in Java. After a while, we just got frustrated with it and abandoned it.

Javascript is a dynamic language, so it’s really easy to stub and mock things out. Use something like Proxyquire to trivially inject mocks in tests.

Integration Testing

Graham’s comments about integration testing being much easier in Java are spot on. I haven’t come across nearly as many drop in, in-memory replacements for connected systems like databases or message queues. This makes it tough to integration test. What I’ve done in the past is to create throwaway Continuous Integration database instances at the beginning of the tests and then clear them out at the end of the tests. It’s not that bad once you set it up once, but I yearn for the ease of using something like HSQL in Java.

Team Development Environments and Docker

My team has half Windows users and half Mac users. It makes for a challenging environment for everyone to setup their development environment in Node.

If you’re on a team with developers using multiple platforms, and deploy to Linux, what I recommend is to create a Dockerfile which defines your development environment. Then, use a Docker volume mount to put your source code inside the container. (Side note: Use an official Node.js Docker image as your base image). This lets you use normal Docker build/run commands to bootstrap your dev environment. The volume mount lets you dynamically update your code so you can still iterate fast, as if you were working on your local machine. It works well across platforms (no worrying about exceptions in Windows), and as a bonus, if you ever want to run your app in a Docker container, you’ve already got it more than halfway there. I’m hoping to post more about this in the future.

Go enjoy!

I’ve been developing in Node for about 3 years now, and I still really love the developer experience. Sure, I’m probably not using the latest and greatest tools that just came out, but this workflow has gotten me to a good place where I can be very productive and crank out some good quality code.

I hope some of these notes help you do the same.

What tools/techniques/libraries did I miss that were important for you when you came to Node from Java?