One of the necessary steps in the growth of any software team is landing on a coding style. Every developer likes to write code a little differently. This is a good thing! Differences of opinion about how to write code allow teams to find novel solutions to problems they face. However, too much difference in terms of coding style can lead to difficulty working with a code base. In my experience, the healthiest software teams I’ve worked on settle on a list of rules for code that they enforce across the entire code base. Then, they take those rules a step further: they codify them into an automatic code-checking system. Called a “linter,” these are programs that examine your code and warn developers when parts of it don’t conform to the team’s rules.
The two foremost linting options for JavaScript codebases are ESLint and JSHint. In this post, we’re going to compare them side-by-side to find what each does well, and why you might choose one over the other.
Documentation
When it comes to code linters, documentation is always one of the most important features. Both ESLint and JSHint are highly-configurable. You can tweak them to fit every nuance of your team’s coding style. But when you first dive in, all the rules are overwhelming. Do you want to turn on the eqeqeq rule? What does it even do? What about curly ?
This is where documentation is valuable. It’s also a place where my opinion is that JSHint has a real advantage. Both libraries have extensive documentation, but JSHint’s options reference is clear and concise. ESLint’s rules reference, by comparison, doesn’t explain nearly so clearly what each rule does. Instead, you need to click through on each rule explanation to read more about it. While both will explain to you how to use their system if you read them, JSHint’s documentation is simpler and more straightforward. One credit that I will give to ESLint, though, is that they provide example code
Error Messages
In addition to documentation, error messages are the other part of the most important parts of a linting library. Error messages are what tell you the mistakes you’ve made in writing your code. Clear error messages make working with a linting library a joy. They also simplify adding a new developer to the team. When that developer writes some code that doesn’t fit your team’s style, a good error message means it’s easy to understand where they went wrong, and what rule they broke. A poor error message causes confusion and frustration.
Error messages are a place where ESLint has a real advantage over JSHint. ESLint’s errors are succinct, but still clearly explain what they’re talking about. They can also provide a small snippet of the code with a carat to indicate where the error triggered during evaluation. ESLint’s swath of configuration options extend to error messages, too. You can define more than a dozen different output formats for ESLint errors. This makes it easy to use those error messages in whatever format you need.
By contrast, JSHint’s error messages aren’t nearly so versatile. JSHint will display errors, with a file name, line number and column number, as well as a short explanation of what’s wrong with the code. While this is useful, it doesn’t compare to the clarity provided by ESLint. The other major shortcoming for JSHint is that it doesn’t provide nearly as many output options. The only output choices are standard and verbose. The verbose output option provides more information. That information is useful, but it still doesn’t stand up to how useful ESLint’s error codes are.
Installation
Both ESLint and JSHint install via NPM and run on the command line. Examining them, JSHint isn’t as popular among developers or teams as ESLint. However, both are still actively developed and well-maintained. Installing each is as simple as running an npm install command. This is a place where neither has a clear advantage.
Initial Setup
While installation is something that comes quickly and easily for both libraries, initial setup is a bit more involved. When it comes to JSHint, you need to define a .jshintrc file in the root of your project. That file contains instructions for JSHint to use while linting your code. Your reference for those rules is the options reference we looked at earlier in the post. Setting up this file can be pretty time-consuming. In my experience, it’s often the place where the most pain happens while integrating a linter into your code base. Code that was perfectly fine yesterday is now throwing an error today. That’s not the kind of change that developers enjoy!
ESLint also requires that you set up a configuration file. However, ESLint comes packaged with an initialization script that simplifies this process. After you install ESLint, you should run npx eslint –init . This command will walk you through a series of options to help you set ESLint up for the first time. It provides an easy way to adopt rule sets used by large engineering teams, or you can walk through a list of rules, see their explanations, and choose to turn them on or off one-by-one. There’s even an option to have ESLint examine your existing code base, then set rules based off the patterns it sees in your code. This avoids the frustration you see in the initial setup process. Code never goes from valid to invalid. Instead, you can slowly tweak rules as the need arises, while ensuring new code conforms to the patterns of old code.
JSX Support
JSX is a syntax extension to JavaScript that’s used by the React UI library. It combines JavaScript syntax with HTML snippets to create dynamic UI components. It’s a powerful way of working, and for my time, the best way to write web applications today. If you write React and you want to use a code linter that understands React, you’ll need to use ESLint. ESLint actually supports JSX syntax right out of the box. You don’t need to set anything additional up; it’ll parse and provide linting for your JSX files just the same as your normal JS files.
JSHint doesn’t have this functionality. It doesn’t support JSX files at all upon initial setup. There was a project intended to provide JSX support to JSHint: JSXHint. Unfortunately, this project is no longer supported and hasn’t been for several years. At this point, the recommended way to provide JSX support in JSHint is simply to ignore the JSX syntax altogether and only have JSHint analyze the pure JavaScript syntax. For some teams, this might be a reasonable compromise. For others, it’s a non-starter. Which kind of team you are is a choice that only your team can make. And obviously, if your team doesn’t write React, this isn’t even a question.
So, Which Should Your Team Choose?
If I were making a choice today on a large JavaScript code base, my choice would be ESLint. Part of the reason is that I write nearly all my UIs in React. But part of the reason is that I find ESLint easier to set up and the messaging it provides to be easier to use. I don’t need to learn how to parse terse error messages from JSHint. ESLint makes it clear what problems it has with my code, and it’s easier to set up. It’s also the more popular library for code linting within the broader JavaScript community. More projects rely on it, and many more people download it per week than JSHint.
With all of that said, I don’t feel like JSHint is a bad choice. If you’re a team that’s already happy with JSHint, should you switch to ESLint? Probably not! ESLint isn’t sufficiently more advanced to throw away the hours of work you’ve spent configuring JSHint just how you like it. And while it’s easier to onboard a new developer to ESLint, the learning curve for JSHint obviously isn’t so steep that it’s impossible to learn. Both are powerful libraries, and while I feel that ESLint provides more advantages, any mature software team would be well-served by either.
This post was written by Eric Boersma. Eric is a software developer and development manager who’s done everything from IT security in pharmaceuticals to writing intelligence software for the US government to building international development teams for non-profits. He loves to talk about the things he’s learned along the way, and he enjoys listening to and learning from others as well.