Godson Obielum I'm a software developer with a life goal of using technology as a tool for solving problems across major industries.

Modern, faster alternatives to ESLint

8 min read 2315

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.

: Full visibility into your web and mobile apps

LogRocket is a frontend application monitoring solution that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page and mobile apps.

.

Contents

  • Advantages of linters and code formatters
  • What is ESLint?
  • Modern alternatives to ESLint
  • Libraries to integrate with ESLint

    Advantages of linters and code formatters

    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.

    What is ESLint?

    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.

    Modern alternatives to ESLint

    Rome

    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.

    Advantages of Rome over ESLint

    Performance

    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.

    Third-party dependencies

    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.

    Features

    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

    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.

    Advantages of quick-lint-js over ESLint

    Performance

    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.

    Small design, fewer features

    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.

    No configuration

    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

    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.

    Advantages of Standard JS

    Simplicity

    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.

    Automatically formats code

    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

    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.

    Advantages of Putout over ESLint

    Applying fixes

    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.

    Minimalistic API

    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

    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.

    • JSHint has basic support for ES6 syntax but no support for ESNext syntax; it also doesn’t support JSX. This may be a deal-breaker, especially when considering it for use in more modern projects
    • JSHint has no custom rule support
    • JSHint has simple, clear, and concise documentation, especially around all the options available for use in a project
    • Unlike JSHint, ESLint’s error messages are pretty detailed and easy to understand because of the natural language used throughout all the messages
    • If a rule is violated and needs to be fixed, JSHint doesn’t show the name of the rule causing an error, making it more difficult to trace

    In summary, for most of the scenarios we’ll encounter, ESLint is a more mature and robust solution to consider among the two.

    Libraries to integrate with ESLint

    Prettier

    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.

    Integrating 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

    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.

    Integrating Babel with ESLint

    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

    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.

    Integrating webpack 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!

    Conclusion

    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.

Godson Obielum I'm a software developer with a life goal of using technology as a tool for solving problems across major industries.

Leave a Reply