JavaScript Import Sorting

It’s fascinating how the order of imports doesn’t matter in individual JavaScript files. If you start awaiting them and using their methods for things, then it might matter, but those top-level normal imports at the top of so many JavaScript files… the order is largely irrelevant.

This:

import React from 'react';
import classNames from 'classnames';
import styles from './ThisComponent.module.scss';
import { QueryWhatever } from './ThisComponent.graphql';

Behaves no differently than:

import { QueryWhatever } from './ThisComponent.graphql';
import classNames from 'classnames';
import React from 'react';
import styles from './ThisComponent.module.scss';

I know we’re not exactly looking at vanilla JavaScript with the non-standard file formats, but it holds true in vanilla JavaScript as well. Also, I’m sure there is nuance to the order in which they are evaluated and when code inside them executes and such, but again, for the code below these imports, that code doesn’t care.

That doesn’t-matter-ness can lead to, well, a mess. It’s common that a project-wide convention determines how best to do it. “React always goes at the top, even if it’s not alphabetical with other npm imports”. “Styles are always last”. “Group together or library components”. That kind of thing. But it’s not always enforced. In fact, I really don’t like seeing Pull Requests with diffs that contained re-ordered imports, as it feels like confusing noise. And yet, I was guilty of doing it, because I like having all the files share a common logical-to-me order.

I’ve tried to automate this in the past and have failed. Either I couldn’t get it going right or I didn’t like the control I had over the output, or something. I think I tried the ES Lint version of it, and part of the problem is that I prefer the automation to happen on-file-save. It could also be in a pre-commit hook also, but I don’t want it only there. And if you want it on-file-save, that’s Prettier territory generally. You don’t want two different things in your code editor fighting over which does the formatting.

Fortunately, there is a third-party plugin for Prettier for import sorting: prettier-plugin-sort-imports. Shaw on our team implemented it recently. That’s a two-part process:

  1. Get it working
  2. Run it against the whole code base and commit it using a throw-away Git user

Both turned out to be no big deal.

The fact that it supports RegEx in the configuration for setting up ordering meant we could match our existing conventions (huge!). In our .prettierrc.js file:

  importOrder: [
    'react', // React itself
    '<THIRD_PARTY_MODULES>', // node_modules
    '^(cplibrary|cpicons|cputil|cpclient|@cpclient|cpshots).*$', // Workspace packages
    'components/.*$', // React Components
    '^(constants|data|hooks|util|utils)/.*$', // Various helpers
    '^(\\.|\\.\\.)/(.(?!.(css|scss)))*$', // Any local imports that AREN'T styles.
    '\\.(css|scss)$' // Styles
  ],
  importOrderSeparation: true,
  importOrderSortSpecifiers: true,
  importOrderCaseInsensitive: true

Those groupings match how our home-grown conventions evolved.

Works great. No more import sorting commit noise and every single JavaScript file sorts the imports in a standardized way, improving scannability.

How nice is this?

Leave a Reply

Your email address will not be published.