27 Comments

Emacs vs. WebStorm for Node.js Development

If you’ve ever worked with me, or read my blog posts, you know I am an Emacs junkie. Emacs is my first and last editor, and I’ll happily spend hours making it just the way I want it.

Lately though, I’ve been doing a lot of Node development and feeling some pain from using my favorite tool. I also recently ended a large Java project where I had been using IntelliJ as my editor, since it was much more advanced than anything Emacs could offer. Since I had been using IntelliJ and some other JetBrains products, I was aware of WebStorm, their IDE geared towards JavaScript development.

I decided to give WebStorm a try and see if it solved any of the pain I had been feeling. After using both tools for JavaScript development for quite a while, I have a good idea of the pros and cons of both Emacs and WebStorm for Node.js development.

Things Both Emacs & WebStorm Do Well

There are a few critical features where both Emacs and WebStorm work just fine. For one, they both do a great job of hooking into external code quality tools like ESLint. Either one can hook into these tools and provide real-time linting and error checking.

Additionally, both tools can provide some deeper analysis of JavaScript code. Emacs has js2-mode, and WebStorm has its own proprietary JavaScript analysis engine. Both of these engines can find issues like functions that don’t return a value, and they can perform trivial refactors like extracting variables.

Lastly, both tools have good support for intelligent auto-completion. WebStorm does this through its own proprietary engine, which, among other things, parses JSDoc annotations and TypeScript descriptor files. Emacs, on the other hand, can be configured to use Tern, which is an open source JavaScript code analyzer that different editors can hook into.

Things WebStorm is Better At / Emacs Can’t Do

While Emacs is great, there are a few things it is just plain worse at or can’t do at all. Critically, all of the most annoying ones are things WebStorm can do, which makes it very appealing.

One of the key features in this category is debugging. The default Node.js debugger is terrible and slow, and WebStorm is the only replacement I’ve found that is worth using. I would go as far as to say the debugger alone makes WebStorm worth having for non-trivial JavaScript development. Emacs has some built-in editor support for debugger integration, but it does not work with the default Node.js debugger. Even if it did, it would likely still be crippled by the very slow performance of the default debugger.

Symbol and definition lookup is another great feature of WebStorm. While Emacs can find symbols and definitions in a single file via Tern, WebStorm can actually inspect your whole project and find a definition, or at least give you a very pruned list of candidates to choose from. This makes navigating through code exponentially faster, and it really reduces the strain of context switching between files.

Testing integration is the last big win for WebStorm. When using the most common JavaScript testing frameworks, Mocha and Jasmine, WebStorm makes it trivial to run individual tests, whole test files, and whole test suites with just a few keyboard shortcuts.

When you combine this last feature with debugging and code navigation between files (or through test failure stack traces), WebStorm becomes an amazing TDD tool. Emacs can be trivially set up to run a whole test suite, but not to run individual tests for any of the common JavaScript testing frameworks. While writing something to do this is entirely possible in Emacs (such an integration exists for Ruby’s RSpec tool), no one, including myself, has invested the time to get it working.

Things Emacs Is Still Better At

Despite all the advantages WebStorm has, there a still a number of things Emacs does better.  One of the simplest is “dumb” auto-completion. I previously mentioned that both Emacs and WebStorm can do some level of intelligent, context-aware completion. The reality of a dynamic language like JavaScript, however, is that many times, there is no contextual completion available because there is too much ambiguity or the code lacks structure.

In these cases, WebStorm just doesn’t offer any completion, leaving you to type everything manually. Emacs does something wonderful in this situation, though. It simply tokenizes all of the words in every buffer of the same type, e.g. every JavaScript buffer, then looks at the characters you have started to type and tries to find a match. Surprisingly, I find that most of the time, if I type around three characters of a word I’ve used before in the project, it will offer me that word as one of the first three to five completion options. This drastically improves my speed, since I only have to type three or four characters of most words.

Another thing Emacs is much better at is Vim emulation. While WebStorm’s Vim emulation is decent, I find frustrating bugs quite often. These include keys not registering, getting into weird states where I appear to be halfway between insert and normal mode, and a weirdly sensitive mouse selection that always seems to put me in visual mode when I don’t want to be. Additionally, some advanced features like macros rarely work right for me, and I have basically given up on using them. It also really irritates me that yanking does not copy things to my system clipboard, which Emacs does by default. I find that whenever I need to do any advanced editing like large find/replacements or macro-driven refactoring, I’m better off just opening the file in Emacs and doing it there.

Lastly, you can pry Magit, the Emacs git source control tool, from my cold dead fingers. I’ll admit that I haven’t even really tried using the VCS management inside of WebStorm because I can’t comprehend anything being better than Magit.

Pain Points Shared by Both Tools

I still have some JavaScript development pain points that neither of these tools (and no tools I am aware of) solve well. A big one is automated refactoring. Automated refactoring in a dynamic language is an incredibly difficult problem. Unfortunately, neither Emacs or WebStorm are able to go much beyond the level of simple variable renames or extractions. This can make refactoring across files a tedious, error-prone process.

In the same vein, both tools are pretty poor at generating code for JavaScript in my experience. Both tools support expanding developer-defined templates, but not much else. WebStorm appears to at least be making strides in this regard. Right now, it can generate a method that you call in code, but only into the same file you are in, and it will often call the method wrong.

My Current Workflow

Currently, my Node development workflow has me using WebStorm most of the time. The fact that it can easily run small subsets of tests, plus debugging and quicker code navigation, all mesh well with my TDD workflow.

I still keep Emacs open to my project, though. I use it to do all of my git work, and also to do complex edits using Vim macros.

What tools are you using for JavaScript development? Is there something better I should check out?