DEV Community

Cover image for Import hierarchy
Diego Silva
Diego Silva

Posted on • Updated on

Import hierarchy

making your imports more elegant and organized | part II

Today we will continue talking about how to make our imports more elegant and organized. For that, we need to talk about import hierarchy.

What is Import Hierarchy?

As the name itself makes clear, import hierarchy is the order of priority of the dependencies imported in our code.

It is very common that our .js and .jsx files import many libraries, components, pages, controllers, services, helpers, styles, that is, a multitude of different file types and data.

The example below is very common in the daily life of a front end developer:

import React, { useState, useEffect } from 'react';
import Button from '~/components/Button';
import { Container } from './styles.js';
import Card from '~/components/Card';
import PropTypes from 'prop-types';
import { combineReducers } from 'redux';
import Main from '~/pages/Main';
import Dashboard from '~/components/Dashboard';
import Home from '~/pages/Home';
import Routes from '~/routes';

function ExampleComponent() { ...
Enter fullscreen mode Exit fullscreen mode

Looking at the code above you may wonder: "I don't see any problem with this code".

And in fact, there isn't. The required dependencies have been imported and are ready to be used.

But if we can make it more organized, why not?

Below I show the same example, only more organized:

import React, { useState, useEffect } from 'react';
import { combineReducers } from 'redux';

import PropTypes from 'prop-types';

import Home from '~/pages/Home';
import Main from '~/pages/Main';

import Button from '~/components/Button';
import Card from '~/components/Card';
import Dashboard from '~/components/Dashboard';

import Routes from '~/routes';

import { Container } from './styles.js';

function ExampleComponent() { ...
Enter fullscreen mode Exit fullscreen mode

In the example above, I ordered the imports as follows:

  • first: all the dependencies that I consider the most important of my application. For example, all those starting with 'react' and 'redux'

  • then: all other libraries and modules installed in package.json. For example, Prop Types, Storybook, Unform, among others

  • then: all internal files, which start with the alias ~/ or @. For example, ~/components, ~/pages, ~/styles, @controllers, @models, and so on. In the post Import custom paths and how this can help you I show you how we can create and configure custom import paths to facilitate the import of our application

  • so: the routes of my application"

  • and lastly: my styles. In this case, files named .styled.js

// first, everything that starts with 'react' and 'redux'
import React, { useState, useEffect } from 'react';
import { combineReducers } from 'redux';

// then all imported modules and libraries
import PropTypes from 'prop-types';

// then anything that starts with an alias '~/pages' or '@pages'
import Home from '~/pages/Home';
import Main from '~/pages/Main';

// then anything that starts with an alias '~/components' or '@components'
import Button from '~/components/Button';
import Card from '~/components/Card';
import Dashboard from '~/components/Dashboard';

// so my routes
import Routes from '~/routes';

// and finally, my styles
import { Container } from './styles.js';

function ExampleComponent() { ...
Enter fullscreen mode Exit fullscreen mode

Of course, maintaining this hierarchy for all our code takes a lot of time, attention, and care.

But it's a good thing we can automate this task, isn't it?

do you think?

Getting to know eslint-plugin-import-helpers

The eslint-plugin-import-helpers is a package that was created by Will Honey, and aims to complement eslint-plugin-import. It brings a very important use case that is still missing from eslint-plugin-import: the order of imports.

About order-imports and how it works

The eslint-plugin-import-helpers brings (as of the date of this post) only the order-imports plugin. This plugin allows you to configure an import hierarchy with just a simple .eslintrc.js configuration file.

Making it happen

First of all, you will need to have ESLint and Prettier configured in your project. If by chance you haven't configured it yet, I suggest you follow this tutorial:

After installing and configuring ESLint and Prettier, we can proceed with the next steps.

Installing and configuring eslint-plugin-import-helpers

At the root of our react project, let's install puglin:

yarn add -D eslint-plugin-import-helpers
Enter fullscreen mode Exit fullscreen mode

Now, let's configure the import-helpers/order-imports rule in the .eslintrc.js file:

// .eslintrc.js
rules: {
  'import-helpers/order-imports': [
    'warn', // displays an alert in the editor
    {
      newlinesBetween: 'always', // inserts a blank line after each priority group
      groups: [
        ['/^react/', '/^redux/'], // first group: everything that starts with 'react' and 'redux'
        '/styled-components/', // second group: everything that is imported directly from the styled-components library. This is to ensure that the first import in styles.js files is always styled-components.
        'module', // third group: everything that is a module (any library listed in the package.json file)
        '/prop-types/', // fourth group: importing prop-types
        '/^~/pages/', // fifth group: all my pages
        '/^~/components/', // sixth group: all my components
        ['parent', 'sibling', 'index'], // seventh group: any parent, sibling, or child file of the current file
        '/routes/', // eighth group: my routes
        '/^~/', // ninth group: all other files imported by the configured alias
        '/styles/', // last group: my styles
      ],
      alphabetize: { order: 'asc', ignoreCase: true }, // configures imports in alphabetical (ascending) order, ignoring case
    },
  ],
}
Enter fullscreen mode Exit fullscreen mode

All ready!

If you have configured prettier to automatically fix ESLint improvement suggestions, whenever this hierarchy is not respected, VSCODE will reorganize the imports automatically as soon as the file is saved.


If you want to see this example in practice, you can take a look at the template I created for React projects here:

GitHub logo coderamos / template-reactjs

This project contains the basic structure for React projects. It also includes my settings for babel-plugin-root-import, eslint-plugin-import-helpers, prop-types, react-router-dom, styled-components and more...


Comment there what you think about this post :)

Discussion (1)

Collapse
diasbruno profile image
Bruno Dias • Edited

Great post, but be careful about changing the meaning of ~, it may cause unintended problems and it will be had to debug.