[Updated] Simplify the require/import paths in your project and avoid ../../../  circles of hell
Tags: javascript, webdev, babel, react
Published: 2019-03-29 17:41:11

---
title: [Updated] Simplify the require/import paths in your project and avoid ../../../  circles of hell
published: true
description: Do you hate seeing ../../../ everywhere in your code? Come along and I'll show you why you should use `babel-plugin-module-resolver` to work faster and write cleaner code.
tags: #javascript #webdev #babel #react
cover_image: https://thepracticaldev.s3.amazonaws.com/i/z9e5om0o04e1biay0des.png
---

Do you hate seeing ../../../ everywhere in your code? Come along and I'll show you why you should use `babel-plugin-module-resolver` to work faster and write cleaner code.

#### Update 1 (3/31/19):
As Pavel Lokhmakov suggested, I've created a new GitHub repo [here](https://github.com/mjraadi/babel-plugin-module-resolver-customize-cra) to achieve the functionality explained in this post without the need to `eject` the app. 
[`react-app-rewired`](https://github.com/timarney/react-app-rewired) and [`customize-cra`](https://github.com/arackaf/customize-cra) are both libraries which let you tweak the `create-react-app` webpack/babel config(s) without using 'eject'.
Simply install these packages as dev dependencies and create a new file called `config-overrides.js` in the project's root directory and put your custom config there. Then all you have to do is to update your npm scrips according to `react-app-rewired` docs.

#### The Inspiration
I never liked writing code like this:

```js
import NavBar from '../../components/NavBar';
```
To me it seemed very confusing, not clean and not maintainable. Imagine somewhere down the line, you needed to alter your project's directory structure. You would have to go through every file and update your code to reflect your changes. Talk about non-maintainabilty!
But I loved the way I would import packages from the `node_modules` directory:

```js
// ES6 import syntax
import React, { Fragment } from 'react';

// CommonJS require syntax
const nodemailer = require('nodemailer');
```
So I was eager to find a way to import/require my custom modules/components just like this. [`babel-plugin-module-resolver`](https://github.com/tleunen/babel-plugin-module-resolver) to the rescue!

### TL;DR
You can find the GitHub repos associated with this article:
https://github.com/mjraadi/babel-plugin-module-resolver-test-app
https://github.com/mjraadi/babel-plugin-module-resolver-customize-cra

#### What does it do?
I'll let the plugin author explain:
> This plugin can simplify the require/import paths in your project. For example, instead of using complex relative paths like `../../../../utils/my-utils`, you can write `utils/my-utils`. It will allow you to work faster since you won't need to calculate how many levels of directory you have to go up before accessing the file.

In case you don't know what `babel` is, it's a JavaScript compiler which is mainly used to convert ECMAScript 2015+ code into a backwards compatible version of JavaScript in current and older browsers or environments. If you're building an app with `create-react-app` or similar libraries, they're using babel behind the scene.

#### Let's get started
Here I will show you how you can use this plugin in an app created by `create-react-app`. Create a new app with the command below:

```
$ create-react-app babel-plugin-module-resolver-test-app
```
`create-react-app` encapsulates the project setup and all the configurations and gives you tools to create production ready apps. Since we need to change babel configuration we need to `eject` our app. Ejecting will move `create-react-app`’s configuration files and dev/build/test scripts into you app directory.

**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
It's fine for our use case because we're building a test app. Go ahead and run the command below:

```
$ npm run eject
```
Confirm and continue.

**Note: at the time of writing this post, there is a bug with `create-react-app` explained [here](https://github.com/facebook/create-react-app/issues/6099). The workaround is to remove the `node_modules` directory and reinstall the dependencies again.**

Install the dependencies:
```
$ npm install
```

Install `babel-plugin-module-resolver` plugin by executing the following command in your project directory:

```
$ npm install --save-dev babel-plugin-module-resolver
```
Open `package.json` file and look for babel config. This is how it looks like after eject:
```js
...
"babel": {
  "presets": [
      "react-app"
    ]
  },
...
```
Now we need to tell babel to use our module resolver and define our root directory and aliases. Edit your babel config section to make it look like this:

```js
...
"babel": {
    "presets": [
      "react-app"
    ],
    "plugins": [
      ["module-resolver", {
        "root": ["./src"],
        "alias": {
          "dir1": "./src/Dir1",
          "dir2": "./src/Dir2"
        }
      }]
    ]
  },
...
```
Now create two directories in `src` directory called `Dir1` and `Dir2`. Our defined aliases will point to these directories respectively. 

Create a component file called `ComponentA.js` in `Dir1` directory and put the code below in it:
```js
import React from 'react';
import ComponentB from 'dir2/ComponentB';

const ComponentA = () => (
  <p>
    Hello from <ComponentB />
  </p>
);

export default ComponentA;
```
Now create `ComponentB.js` in `Dir2` directory with the code below:
```js
import React from 'react';

const ComponentB = () => (
  <a 
    href="https://www.bitsnbytes.ir"
    className="App-link"
    target="_blank"
    rel="noopener noreferrer"
  >
    Bits n Bytes Dev Team
  </a>
);

export default ComponentB;
```
Now edit the `App.js` file in the `src` direcory:
```js
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
import ComponentA from 'dir1/ComponentA';

class App extends Component {
  render() {
    return (
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <ComponentA />
        </header>
      </div>
    );
  }
}

export default App;
```
Notice that I didn't have to go up one directory or down another directory to import my components. We're now ready to run our app, run the command bellow in your terminal:
```
$ npm start
```
You should see your app in the browser without any problem. If you have any questions or problems, feel free to comment.

### Conclusion
Custom module resolvers will save you time and the frustration of dealing with ../ splattered everywhere. They take a bit to setup and ensure full cooperation with existing tooling, but the result and visual satisfaction of never having to see ../../../../../.. is well worth the initial outlay on big projects.

### About Me
I am a full stack web developer and co-founder of [Bits n Bytes Dev Team](https://www.bitsnbytes.ir), a small group of highly talented and professional freelance developers, where we provide custom web application development services based on cutting-edge technologies, tailored to client's unique business needs.  

I'm available for hire and you can check out my portfolio website at https://www.bitsnbytes.ir/portfolio or contact me at raadi@bitsnbytes.ir.