Skip to main content

How ESLint Made Our Codebase Breathe Again

Tooling January 25, 20243 min read

Every engineer has had that moment: opening a file and being greeted by chaos. Lines of imports scattered in no particular order. Some duplicated, others grouped inconsistently — almost like a visual reminder of how many hands had touched the file over time.

That’s how it felt every time I opened a file in our frontend repositories. It worked, the code always ran. But it didn’t feel right; it was messy, inconsistent, and every new import added to the tangle.

And that’s where this story begins — not with a broken feature or a failing test, but with a quiet frustration and a small, simple goal:

Leave the codebase cleaner than I found it.

The Chaos of Imports

In the wild, our imports looked something like this:

import { Link } from 'react-router-dom';
import Toaster from '../Toaster';
import PropTypes from 'prop-types';
import React, { useState, useRef, useEffect, useCallback } from 'react';
import classNames from 'classnames';

Nothing technically wrong — but visually? Hard to scan, hard to maintain.

I imagined what it could look like instead:

import React, { useCallback, useEffect, useRef, useState } from 'react';
import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
import classNames from 'classnames';
import Toaster from '../Toaster';

Same imports, different energy.

It reads naturally — from framework to libraries to internal components. You can almost feel the logic.

The Idea: Automate Boring Stuffs

That small spark led me to ESLint — specifically, its sort-imports and import/order rules.

The goal wasn’t just to enforce order; it was to encode our sense of craftsmanship into the code itself.

  • sort-imports ensures the items on each line stay sorted.

Using the configuration:

"sort-imports": [
      "error",
      {
        ignoreCase: true,
        ignoreDeclarationSort: true,
        ignoreMemberSort: false,
        memberSyntaxSortOrder: ["all", "single", "multiple", "none"],
        allowSeparatedGroups: false,
      },
    ],
import React, { useEffect, useState, useCallback } from 'react';

is corrected to

import React, { useCallback, useEffect, useState } from 'react';
  • import/order organizes entire groups — built-ins, externals, internals — like chapters in a well-structured book.

I configured them to follow this pattern:

[["builtin", "external"], "internal", ["parent", "sibling"]]

And because conventions matter, I gave react, react-dom, and PropTypes reserved spots at the top — the familiar trio that should always greet you when you open a React file.

"import/order": [
      "error",
      {
        groups: [["builtin", "external"], "internal", "parent", "sibling"],
        pathGroups: [
          {
            pattern: "react",
            group: "external",
            position: "before",
          },
          {
            pattern: "react-dom",
            group: "external",
            position: "before",
          },
          {
            pattern: "prop-types",
            group: "external",
            position: "before",
          },
        ],
        pathGroupsExcludedImportTypes: ["react", "react-dom", "prop-types"],
        "newlines-between": "never",
        alphabetize: {
          order: "asc",
          caseInsensitive: true,
        },
      },
    ],

The result? Code that looks and feels organized:

Package import chaos

Every file started to breathe better.

The Fixing Marathon

I ran yarn lint --fix with the same nervous excitement as running tests after a big refactor. Some files cleaned themselves up perfectly. Others resisted. After the auto-fix, I was left staring at 225 stubborn files that needed manual care — one by one.

It wasn’t glamorous work, but it was meaningful. Each file I fixed became a little more readable, a little more consistent.

And consistency is contagious.

The Hidden Problem: Duplicate Imports

While working on the imports, I found another recurring issue — duplicate imports. Same package imported twice in the same file. Easy to miss, but messy and unnecessary.

Examples like these kept popping up:

import { useHistory } from 'react-router-dom';
import { useFeatureFlags } from '../../contexts/FeatureFlagContext';
import { Link } from 'react-router-dom';

So I added one more rule to our ESLint configuration:

"no-duplicate-imports": "error"

Now, ESLint not only helps us keep things tidy — it protects us from repeating the same mistakes.

Final Thoughts

At first glance, sorting imports doesn’t seem revolutionary. But it’s symbolic of something deeper: Care. When developers take time to improve the small things — the things no one notices until they’re wrong — they build a culture of pride and respect for the codebase.

Every lint rule, every refactor, every cleanup is a way of saying:

“I was here — and I left it better than I found it.”


Share this article:

Stay Updated