What's the difference between ESLint and Prettier?

In the last blog post we had a look at how to build our own little linter that checks for most common errors in JavaScript code. While this exercise taught us why we need linters and where they can be used, we commonly use linters built by other people.

In this blog post we're going to have a look at how different linting tools for JavaScript have evolved in the past and where we have come with the modern variety of tools.

Static code analysis

Code linting can be seen, in a more broad sense, as static code analysis. Static code analysis is a type of program that reads static (= not interpreted or executed) code and checks for different kinds of things that might be going on in the code — like our little regular expression code checker in the previous post.

Fortunately someone else did already think about doing this for JavaScript before us. Way before. That someone was Douglas Crockford, and the year was 2002. Douglas then started to work on a static code analysis tool for JavaScript called JSLint, which was a simple website where you could paste your code and it would check for any common errors.

In 2010 the single-author JSLint project was forked to a community-driven JSHint, which grew popular with the JavaScript developer community after being published as a NPM module that could be run from the command line (like our small but pretty linter script from previous post).

JSHint was popular, modularized and unopinionated. You could change which rules the JSHint matched by your own preferences (tabs vs. spaces, anyone?), and you could even turn it of line by line if you wanted to do an exception to the rules:

/* jshint evil: false */
/* jshint evil: true */

Although JSHint was a great project, it did not adopt to changes fast enough. In 2013, a small project called JSCheck was renamed to ESLint. ESLint was a fresh take on static JavaScript analysis: It used a library called Esprima for parsing the code.

To understand what it meant to the JavaScript's static analysis, we'll have to take a couple of steps back and see what ECMAScript means.

The tale of ECMAScript

ECMAScript is a language specification created in 1997 to standardize the then-obscure JavaScript. Back then there were two different implementations of the language: Netscape's JavaScript and Microsoft's JScript. The ECMAScript standard was created to provide a cross-browser compatibility between the two. After implementing the new standard, Microsoft still continued to call their implementation with the name JScript for several years because of trademark issues.

As the years went by, ECMAScript gained more implementations of the standard, each with their own use case. For example the Web2.0's shiniest toy — the Flash file format — was usually programmed using an ECMAScript compliant ActionScript language.

Fast-forward to the year 2014, so not too long after the ESLint tool's release, there was a huge update coming up in the JavaScript scene: Version 6 of the ECMAScript standard (commonly called ES2015 or ES6).

Browsers were slow to adopt the new features like promises, block-scope variables and arrow functions — but there was a project called 6to5 that sped up the developer community's adoption.

6to5 was a transpiler that allowed anyone to write ECMAScript 6 compliant JavaScript, and transformed the ES6 code to browser-compatible version of the JavaScript: ECMAScript 5 (thus the name, 6to5). Later in 2015 the project 6to5 was renamed to Babel.

Fast adoption of ECMAScript 6 was fortunate for the ESLint project. The previous JSHint was in no condition to support the new ECMAScript 6 version's syntax in JavaScript, while ESLint supported all the new features out of the box, all thanks to the underlying ECMAScript-compilant Esprima library.

Nowadays ESLint seems to be the de-facto static code analysis tool for JavaScript. It has grown even more popular after its own configuration system, that allowed developers to take some well-known code styling guide (like the famous AirBnB JavaScript style guide) and start formatting their code accordingly.

Fixing or formatting?

More recently ESLint also has implemented the --fix flag, which automatically tries to fix as many errors as possible, bit like the code formatting tool gofmt for the Go language.

This is convenient, as you might want to start enforcing some new code formatting style in your project (like removing all the semicolons), and the --fix flag allows you to write a single command that goes through all your code files and fixes them to use the new ruleset.

Yet ESLint has one big issue in its initial design: It was first designed to look for syntax errors in the code and only then manually fix all the errors if it was possible. This approach works well in simple cases like forcing a strict equality sign over loose equality sign, because there is only one way to fix that error.

Let's consider a more complex example: Line length. Developers commonly want to restrict themselves to some sane maximum line width like 80 characters. This is easy to write as a linter rule: For our own regular expression syntax checker this is implemented as following rule:

const checkForTooLongLines = /^.{80}.+$/g

This rule takes each line, skips the first 80 characters and only returns a positive match if the line has any extra characters over the 80 character limit.

But how could we auto-fix this issue? There are quite many possible scenarios where we can exceed the 80 character limit — especially in a situation with many nested if-else blocks or callbacks where each indentation of a block will reduce the amount of characters that fit in the line.

Because there are a big number of possible causes for this rule to break, there are even more ways to fix the issue. For example we can split the following one-liner into several lines in many ways:

const abc = { { a: 1, b: 2 }, c: 3 }

const abc = {
  { a: 1, b: 2 }
  c: 3

const abc = {
    a: 1,
    b: 2
  c: 3

Even this problem is solvable using a modern tool called Prettier. JavaScript formatting tool Prettier was released in 2017 by James Long, taking inspiration from refmt tool that's used with Facebook's Reason project that leverages OCaml's syntax to work in harmony with JavaScript.

James used the existing project Recast as a base for Prettier. Recast was already doing the hard work: Reading the code, parsing it to abstract syntax tree (AST) and transforming it to a better format.

Behind the scenes the Recast library is using the familiar Esprima library to parse the code — but it also exposes a print function to output the formatted code.

James took this concept of not only linting, but also formatting the code automatically and lifted it to next level by using code formatting concept from Philip Wadler's white paper "A prettier printer". In the beginning of the paper Philip states:

Joyce Kilmer and most computer scientists agree: there is no poem as lovely as a tree. In our love affair with the tree it is parsed, pattern matched, pruned — and printed. A pretty printer is a tool, often a library of routines, that aids in converting a tree into text.

The white paper describes a method of describing the best format for codes that:

While implementing Prettier, James took the concept from Philip Wadler and added some of his own opinions to make the resulting layout work better for modern JavaScript development. For example, the Prettier formats JavaScript's Promise chains better than the initial white paper's implementation:

// Original implementation from "A prettier printer"
hello().then(() => {

// Prettier uses the more common way of formatting:
  .then(() => {

The Prettier code formatter uses many clever ways to format your code better, but more importantly it describes a set of rules to format your code in one single beautiful way.

This helps you as a developer to concentrate on only what's important: What the code does. Prettier takes all the guesswork out of the formatting, especially helping developers to collaborate better together by determining a single source of truth to formatting code that's already validated by some of the industry's top projects like React and Babel.

Prettier is also extended to work on more languages than just JavaScript: It currently supports formatting JavaScript, TypeScript, CSS, SASS, and many more common languages you'll find in a modern web project.

However Prettier does not yet replace the use of a modern linter completely; while Prettier shares many features with a linter, it can still be beneficial to include a specific linter in your project to catch all possible mistakes in the code. An example would be the no-var declaration of ESLint, which checks for any var assignments in your code; if you want to make sure you don't use var (function level/global variable assignment) in your code, you still need to use ESLint to check it.


A great project is made out of consistent code. In the perfect world the code should be indistinguishable from its writer: You should not be able to tell who authored which line of code in the project.

Modern linters and formatters help to narrow this gap by defining a clear set of rules that are enforced to all the developers working on that project. These tools also help developers to write better code by pointing out common errors and enforcing good programming patterns.

This is especially valuable when working on a team of developers with different backgrounds. More junior developers can adopt to common practices by following the rules and you can be certain that the code stays consistent even when the practices change over time.

In the next blog post we're going to take a mental trip to the early days of the Internet and find out how terms like HTTP and REST came to existence. Subscribe to the mailing list below to receive a notification when the new blog posts are out!

Read the next post here:

You don't know the difference between HTTP and REST


Be the first to know from new blog posts

Subscrbe to the mailing list to get priority access to new blog posts!