Linting ES2015+ — ESLint with StyleGuides: Google, AirBnB, Common
One refrain I return to over and over again when I tutor web development is that most bugs during development are caused by typos. That could be an improperly placed semicolon or a failure to close a section of code. These kinds of code errors rarely make it into production code. However, spending time weedling them out is frustrating and wasteful, especially because there’s a better way. Enter linting, or static code analysis.
Linting — Purpose and History
A linter is a small program that checks code for stylistic or programming errors. (source) The term “lint” was coined in for a program which checked C code for errors before compilation. My best speculation on the reason the term was chosen is that it’s a metaphor for removing lint from a sweater. Get those little bits and pieces off your clothes so that you’re clean and ready to run. Using a linter, the developer can use software to do what it does best — quickly assess a large set of data to see if it conforms to specific rules.
The first JavaScript linter was released in 2002 by Douglas Crockford, called JSLint. This package was downloaded 84,385 times in the past month on npm compared to 10,880,367 downloads for ESLint in the same time period. There are two reasons why JSLint has less than 1% of the usage of ESLint as judged by monthly npm downloads, despite the fact that it was actually released first.
- JSLint uses a license that is derivative of MIT except for the addition “The Software shall be used for Good, not Evil.” This addition makes the software “not-free” and has slowed, though not completely stopped, adoption by large organizations such as IBM.
- JSLint does not allow for configuration, which means it enforces a single style guide, Douglas Crockford’s style guide. This is a strict style guide, and fully following it is a challenge few applications could reasonably achieve. It’s discussed elsewhere.
Because of how strict JSLint was, it was eventually forked into JSHint, eight years after the release of JSLint in 2010. JSHint finally allowed for configuration. Five years later, ESLint broke onto the scene with the ability to disable rules on individual lines. This functionality explains why ESLint currently enjoys approximately 5x the user base on npm compared to JSHint.
Recently, the Prettier package has taken the JavaScript world by storm. I haven’t used it yet and as such I won’t be covering it here.
Bike-Shedding about Code Style
Beyond eliminating typos and errors, there’s a greater question of consistent code style in a project. While it’s certainly possible to code at great speed without a consistent style or enforced rules, this becomes much more difficult as a team grows. Consistency in code style leads to much easier comprehension among teammates, quicker code reviews, and fewer bugs.
The greatest issue is not which style to choose, but rather consistency of style. I have, in the past, been accused of “bike-shedding” (i.e. Discussing what color to paint the bike shed next to the nuclear power plant we’re supposed to be designing) about code style. The reason I wanted to talk about it is because I am aesthetically driven, and the aesthetics of my code is important to me. That experience lead me to promise to myself never to accuse anyone of bike-shedding. I would never accuse anyone of that because I think to accuse someone of bike-shedding is to say “Whatever this thing is that matters to you, it doesn’t really matter. You are being frivolous to discuss this.” I would never say that to someone, so I won’t accuse anyone of bike-shedding. If you also refrain from accusing others of bike-shedding, thanks. :+1:
That said, time spent on protracted discussions on the benefits of one code style over another can usually be better spent writing actual code. Putting some thought into choosing a code style for a whole team to follow, however, is a good use of time. In the interest of making the process faster, here’s some information about the three most popular JavaScript code style guides.
If you know of any other popular code styles you are interested in comparing to these, let me know if the comments below.
Comparing Style Guides
While working on introducing ESLint to a project that hadn’t used it before, I was faced with the open-ended question of which style guide to use. When trying to decide what to use for the project, I wanted to see a simple comparison of the most popular options. I wasn’t able to find a post quite like that, so I decided to write one. I’m comparing style guides for use with ECMAScript 2015+, including seeing what React with JSX support is like. All examples will be the default style behavior of each style guide with no additional rules added.
In order to put us in the ES2015+ environment including being able to use modules, set up your .eslintrc.js as such:
module.exports = { "env": { "browser": true, "es6": true }, "parserOptions": { "ecmaFeatures": { "experimentalObjectRestSpread": true, "jsx": true }, "sourceType": "module" }, "extends": "[this is where you'll put the guide name]" };
ESLint Recommended
"extends": "eslint:recommended"
This is not a very strongly opinionated style set. It’s especially useful if you’re not concerned with code style per se, and are more invested in simply catching unused variables or syntax errors.
Commonalities
The most interesting discovery from this exercise was seeing what was actually the same among these three major JavaScript style guides.
- Tabs: 2-Spaces
- Quotes: Single
- Brace Style for Control Blocks: Same Line
- Prefer Const over var: Yes
- No Trailing Spaces: True
Google JavaScript Style Guide
"extends": ["eslint:recommended", "google"]
- Tabs: 2-Spaces but 4-Spaces is not flagged
- Semicolon: Required
- Trailing Commas: Required
- Template strings: No preference
- Import Extensions: No preference
- Object Curly Spacing: None
- Array Bracket Spacing: None
- Parentheses Around Arrow Function Arg: Required
- JSDocs: Required (!)
- Console statements: None
- Underscored functions: Allowed
- Space before function parentheses: None
This is my last choice due to my being a React developer. Google does not have a React style guide because it is the developer behind Angular, the predecessor and primary competitor of React. Here’s an ES2015 code sample with Google
import 'whatwg-fetch'; export const CONSTANT = 'constant'; export const formatData = (data) => { let topics = []; if (data.topics) { topics = data.topics .sort((a, b) => a.position - b.position) .map((topic, topicIndex) => { const id = topic.name + '-topic-' + topic.position; return { ...topic, id, position: topicIndex + 1, title: topic.name, }; }); } else { const id = data.id + '-topic-0'; const title = null; topics = [{ id, title, }]; } const formattedData = { id: data.id, topics, }; return formattedData; }; ...success: function(data)... // no space ...this.setState({error: textStatus});... // no spaces
AirBnB
"extends": ["eslint:recommended", "airbnb"]
- Semicolon: Required
- Trailing Commas: Required
- Template strings: Prefer
- Import Extensions: None
- Space before function parentheses: None
- Object Curly Spacing: Yes
- Array Bracket Spacing: None
- Underscored functions: None
- Object Destructuring: Prefer
- React Ordering: Opinionated
- React Prop Validation: Required
- Arrow Functions Return Assignment: No
- Object Property Shorthand: Prefer
import 'whatwg-fetch'; export const CONSTANT = 'constant'; export const formatData = (data) => { let topics = []; if (data.topics) { topics = data.topics .sort((a, b) => a.position - b.position) .map((topic, topicIndex) => { const id = `${topic.name}-topic-${topic.position}`; return { ...topic, id, position: topicIndex + 1, title: topic.name, }; }); } else { const id = `${data.id}-topic-0`; const title = null; topics = [{ id, title, }]; } const formattedData = { id: data.id, topics, }; return formattedData; }; ...success: function (data)... // space ...this.setState({ error: textStatus });... // spaces
Standard
"extends": ["eslint:recommended", "standard"]
- Semicolon: No
- Trailing Commas: No
- Template strings: No preference
- Space before function parentheses: Required
- Console Statements: None
- Underscored functions: Allowed
- Arrow Functions Return Assignment: Never
- Import Extensions: No Preference
- Object Curly Spacing: Consistent
- React Ordering: Not opinionated
- React Prop Validation: Not required
import 'whatwg-fetch' export const CONSTANT = 'constant' export const formatData = data => { let topics = [] if (data.topics) { topics = data.topics .sort((a, b) => a.position - b.position) .map((topic, topicIndex) => { const id = topic.name + '-topic-' + topic.position return { ...topic, id, position: topicIndex + 1, title: topic.name } }) } else { const id = data.id + '-topic-0' const title = null topics = [{ id, title }] } const formattedData = { id: data.id, topics } return formattedData } ...success: function (data)... // space ...this.setState({ error: textStatus })... // No opinion spaces
Shareable Configs
A pluggable and configurable linter tool for identifying and reporting on patterns in JavaScript. Maintain your code quality with ease.
Visit the ESLint docs for Sharable Configs to learn how to create your own sharable code style, for when these options don't give you everything you need.
Round Up
In general, semi-colons required or not is going to be the first break point. If you feel strongly in favor of dropping semi-colons, go with Standard. Standard is a challenging style to sell to existing teams due to it opting out of semi-colons. While I personally like JavaScript without semi-colons, many developers have used them for many years and resist dropping them.
If you want semi-colons, the choice is between Google and AirBnB. If React is being used, AirBnB offers smart React choices out of the box. Taking React out of the equation, AirBnB seems to be more strongly opinionated of the two. With a few exceptions, AirBnB seems to share many of Google’s style choices but then adds more in besides. Notably, Google required JSDocs, a dubious choice considering how little they’re used in the industry. AirBnB requiring template strings instead of concatenation is another choice I’d consider not a best practice.
If you prefer a lighter touch from your linter, Google is probably the best choice. If you are interested in having a strongly opinionated linter that provides additional validation and React support out of the box, AirBnB is the style guide for you. As always, you can always jump into the eslintrc to disable or enable specific rules. For instance, turning off JSDocs in Google or template strings in AirBnB. In general best practice would recommend finding the style guide that most closely meets your needs, then adding a very limited number of customizations. Hopefully over the next few years the industry will move towards greater regularity of JavaScript style, such as 2-Space tabs.
Winner
AirBnB is the winner of this roundup! It’s got react support out of the box. It’s got opinions and it’s not afraid to enforce them. Could its suggestions even make you a better programmer? Some people might say that. ;)
Let me know if you liked this post and if you have any questions about JavaScript style guides or the use of ESLint. Leave a comment below using Disqus and check out my other posts on web development and the tech industry in general. Thank you.
The original version of this post can be found at Medium at https://medium.com/@uistephen/style-guides-for-linting-ecmascript-2015-eslint-common-google-airbnb-6c25fd3dff0