In this article, we will look at specific open source libraries that either serve as alternatives to ESLint or can be integrated with ESLint. Some of these libraries are built to outright replace ESLint and improve on aspects such as performance or developer experience. In contrast, other libraries are not meant to replace ESLint but are supplemental, i.e., they leverage its features by integrating with it, thereby providing a more robust set of features. We’ll focus on libraries that work well within the JavaScript ecosystem.
Before we get into the meat of the article, let’s briefly look at what linters and code formatters provide and why we may want to use them when working on a project.
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
The core purpose of a linter is to help you improve your code. This improvement is made possible by analyzing your code and informing you of emerging problems based on custom or default rulesets that have been preconfigured. These rulesets are called rules
in ESLint. In essence, through these rulesets, linters help development teams achieve a consistent coding style and find bugs that may occur due to inconsistent coding styles.
On the other hand, a code formatter enforces a consistent style by parsing your code and reprinting it with its own rules. It takes your code editor’s maximum line length setting into account and wraps code when necessary. An example of a famous code formatter is Prettier; we’ll go in-depth into it in the coming sections.
ESLint falls under the category of a linter that we went through in the previous section. It is one of the most popular JavaScript linting tools available and currently has around 24 million weekly downloads.
It primarily excels at doing two things: it finds problems with your code, and fixes them automatically. ESLint is either built in to most text editors or available to be integrated as extensions, indicative of its widespread popularity. It is highly customizable, and you can extend upon the default rules to write custom rules based on your project’s needs.
ESLint’s parser is syntax-aware (it can understand the relationship between your code syntax) so your chances of encountering inconsistent errors produced by traditional find-and-replace algorithms are pretty low.
Next, let’s look at two classes of libraries: those that can serve as alternatives to ESLint and those we can integrate with ESLint.
Rome is a toolchain that aims to unify functionality (such as formatting, linting, bundling, etc.) provided by multiple libraries. It is designed to replace ESLint and other tooling libraries in the JavaScript ecosystem, such as Babel, webpack, Prettier, and others.
Rome aims at building upon a joint base to deliver a solid experience for processing code, displaying errors, and configuration. Rome has strict conventions that it enforces, allowing only minimal configuration. Rome also has first-class IDE support, with a sophisticated parser representing the source text in full fidelity, and top-notch error recovery.
Initially, Rome was built in JavaScript but is now being re-written in Rust; the intention is that such a fundamental shift in the architecture will bring massive improvements in performance, memory usage, and type safety without compromising on other areas such as flexibility.
Through Rust, the developers can create internal APIs that focus on essential needs such as correctness rather than depending on third-party JavaScript dependencies. This is a result of the emphasis by Rust and its community which allows Rome to use dependencies from the community without making tradeoffs around code size and performance.
Rome is much more than a linter, it is a combination of several tools under one library, and therefore, Rome provides way more functionalities and features than ESLint.
Rome is still in development, although the parsing and code formatting features have been released and are available through npm. In summary, its aims are lofty, and with time it could be a significant disruptor to tooling in the JavaScript ecosystem.
Quick-lint-js is a JavaScript linting tool; it helps us find bugs in our JavaScript program and gives us instant feedback on our code, highlighting syntax errors where necessary. It is minimalistic and allows us to use the tool without custom configurations or extra plugins. Quick-lint-js is designed to be an alternative to ESLint, and there are certain aspects in which it excels over ESLint, so let’s take a look at some.
According to these benchmarks, against certain constraints such as input latency, quick-lint-js is over 130 times faster than ESLint. The benchmarks also help its claim as the quickest JavaScript linter and the least energy consumer.
Quick-lint-js’ minimalistic design contributes to its performance as less infrastructure and fewer components reduce runtime parsing costs, meaning quick-lint-js can sooner give feedback on syntax errors.
It works out of the box and doesn’t require any custom configuration files to get it working.
Quick-lint-js is a worthy choice to consider, especially if you’re looking at high performance, ease of use, and less bloat due to size. However, ESLint still reigns as king in community support, the number of rules supported, and custom configuration/customizability.
Standard JS is a JavaScript linter, code styler, and formatter. It enforces a zero-configuration approach rather than the custom configuration used in ESLint through an .eslintrc.json
file. This is exemplified by the fact that users must prioritize community conventions over personal style.
Standard JS provides a straightforward way to enforce code quality in a project by completely removing the possibility of custom configuration. There is no .eslintrc.json
kind of configuration file to manage; Standard JS manages everything for us.
Standard JS provides a simple command to fix inconsistent code by running standard --fix
.
Standard JS is worth considering if you’re okay with using conventions and style guides created by the community. However, if you need the flexibility of custom configuration based on team/personal preferences, ESLint is better.
Putout is a code transformer based on Babel and has inbuilt support for ESLint. It is highly configurable and leverages a plugin system, meaning all rules are available as plugins. This keeps the initial API minimal and allows developers to extend upon it by installing only the rules they need.
Putout consists of three core modules: Parser (parses the code in the abstract syntax tree and then unparses that back to code), Loader (handles the plugin), and Runner (executes the plugins). It works mainly with JavaScript but is also available for use with other languages like TypeScript, YAML, and Markdown. Let’s look at comparisons with ESLint and where we may want to use it over ESLint.
ESLint generally avoids applying complex fixes that could change the runtime behavior. On the other hand, Putout can make these more drastic code transformations that directly affect your codebase.
Due to its plugin-first architecture, the initial API is kept as lean as possible, preventing unnecessary bloat and allowing the developer the choice of extension. Some plugin rules are also smaller than those available in ESLint, e.g., the debugger rule.
We can also use Putout with ESLint by allowing Putout to handle code transformations while ESLint handles any formatting broken after the code transformation. We can use the plugin eslint-plugin-putout to help with this integration.
JSHint was created as a more configurable version of JSLint; it was released in 2011 by John Crawford, and similar to ESLint, it helps us detect syntax errors in a JavaScript program.
As it aims to be a configurable version of JSLint, and provides a plethora of options that can be disabled or enabled through a configuration file, which allows for some form of flexibility. Each available option is also adequately documented.
JSHint comes with support for many frameworks such as JQuery, Mocha, and Node.js, and is also available as a plugin for many popular code editors.
In summary, for most of the scenarios we’ll encounter, ESLint is a more mature and robust solution to consider among the two.
Prettier is a code formatter. It provides support within the JavaScript ecosystem and specific other languages like Markdown and JSON. Prettier takes our code and reprints it from scratch, taking the line length into account and wrapping code where necessary. It strips away all default styling and ensures that the formatted code conforms to a consistent style.
Prettier enforces a consistent code style across the entire codebase because it parses away any original styling and re-prints the parsed AST (Abstract Syntax Tree) with its own rules. Unlike Rome, Prettier is not an outright alternative to ESLint, but we can configure Prettier for code formatting while using ESLint’s code quality rules for catching bugs.
Let’s take a look at how to integrate prettier with ESLint.
I must admit that many guides are available on the internet for configuring Prettier to work with ESLint. This typically varies based on the JavaScript framework and project environment, but we’ll look at a straightforward approach to integrating both in a vanilla JavaScript application.
The first thing to do is install ESLint and Prettier for your code editor. For VS Code editor, we can find the extensions for ESLint and Prettier on the VS Code extensions marketplace.
Next, we’ll have to install three packages; type the following command in the terminal:
npm install --save-dev eslint eslint-config-prettier eslint-plugin-prettier
The eslint-config-prettier package disables all ESLint rules that might conflict with Prettier. This lets us use ESLint configurations without letting it get in the way when using Prettier. We can then use the eslint-plugin-prettier package to integrate Prettier rules into ESLint rules.
Finally, we must set the Prettier rules in the ESLint configuration file. Add the following configuration to the .eslintrc
file in the root directory of the application:
{ "extends": ["prettier"], "plugins": ["prettier"], "rules": { "prettier/prettier": ["error"] }, }
And with that, we should be able to use Prettier with ESLint in our project seamlessly, and there shouldn’t be any problem concerning rule conflicts between both libraries.
Babel is a JavaScript compiler mainly used to transform code from later ECMAScript versions (ES6+) to earlier ECMAScript versions, so it provides backward-compatible versions for current and older browsers or environments.
We can use Babel to transform syntax, provide a polyfill for unavailable features in the target environment, and source code transformations. Babel supports the latest ECMAScript features through syntax transformers; they allow us to use the newest syntax without waiting for browser support.
Like Prettier, Babel isn’t an alternative to ESLint but can leverage ESLint’s linting features to provide our application with a much more robust set of features.
ESLint’s default parser and rules only support the latest final ECMAScript standard and do not work on experimental features. Therefore, we have to use an npm library – @babel/eslint-parser – to run ESLint on valid Babel code.
Let’s look at a simple way to set up this library in an existing Babel project. Head over to the terminal and run this command to install the library:
npm install eslint @babel/eslint-parser --save-dev
Once again, when the installation completes, go to the .eslintrc.js
file (this is typically where we’d configure ESLint) and set this as the preferred parser:
module.exports = { parser: "@babel/eslint-parser", };
Voila, we should now be able to use ESLint for linting our Babel code. There’s also a guide in the documentation for advanced configurations.
Webpack is a static module bundler for modern JavaScript applications – this means that it takes our JavaScript code and its dependencies and builds them into a single file. Webpack identifies all the dependencies (including images and other non-code files) in an application and builds a dependency graph internally. It then makes this into several bundles that can be loaded onto the browser.
Webpack doesn’t require any configuration by default to work, but it supports custom configurations for more complex projects. Let’s look at how we can configure webpack to work with ESLint.
Webpack has a robust plugin system that allows the community to provide otherwise unavailable features. To make this easy, we’ll leverage a popular community plugin to integrate webpack with ESLint.
In an existing webpack project, head over to the terminal and run this command:
npm install eslint-webpack-plugin --save-dev
When the installation completes, add this option to the existing webpack configuration file:
const ESLintPlugin = require('eslint-webpack-plugin'); module.exports = { // ... plugins: [new ESLintPlugin(options)], // plugin options // ... };
The plugin configuration also takes specific options; we can find all the available options here. It’s that straightforward to integrate webpack with ESLint!
That’s all! We learned about linters, code formatters, and also looked at some popular libraries that provided such functionalities. We were also able to go in-depth into some of the alternatives to ESLint and finally looked at how ESLint can be integrated with some of these libraries to provide us with a more robust set of functionalities.
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowCompare Prisma and Drizzle ORMs to learn their differences, strengths, and weaknesses for data access and migrations.
It’s easy for devs to default to JavaScript to fix every problem. Let’s use the RoLP to find simpler alternatives with HTML and CSS.
Learn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
Bypass anti-bot measures in Node.js with curl-impersonate. Learn how it mimics browsers to overcome bot detection for web scraping.