Fixing import path hell (React Native, ESLint, VS Code)

Eightyfive
Beqode
Published in
2 min readJun 11, 2019

This article was originally published on beqode.com with proper code highlighting & style

I see several advantages to getting rid of the import path hell:

  • Easier to move files around (inner file imports relative to project root)
  • Easier to refactor import paths (think “Find & Replace”)
  • Easier to locate a file (mental model)

That said, it should not come at the cost of a lesser Developer experience. If aliasing a folder breaks an ESLint rule and/or prevents code navigation (“Go to definition”), it’s a no go.

Let’s see how to setup a complete folder aliasing solution.

Metro bundler

The React Native metro bundler comes with a nice little feature that allows you to alias sub-folders.

Given this app file structure:

$ tree -d ./src/./src/
├── config
├── services
├── views
│ └── atoms

Adding a simple package.json inside the src folder:

// ./src/package.json{
"name": "app"
}

Will allow you to import files relative to the chosen “app” alias:

import Config from 'app/config';import Api from 'app/services/api';import Button from 'app/views/atoms/button';

Source: https://www.belighted.com/blog/react-and-react-native-directories-management

VS Code

Now we need to tell VS Code (IntelliSense) how to resolve those aliased paths.

// ./jsconfig.json{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"app/*": ["./src/*"]
}
}
}

Source: https://code.visualstudio.com/docs/languages/jsconfig#_using-webpack-aliases

ESLint

One of the most useful & helpful ESLint plugin that I came across is eslint-plugin-import.

eslint-import-resolver-node

In my example, I decided to alias the src folder “app”. If I had decided to go for the simpler case and alias my src folder “src”, I could have used the standard eslint-import-resolver-node resolver.

And I would simply have to tell this resolver where to load the “Node modules” from, adding the app root folder as another moduleDirectory:

// ./.eslintrc.yaml# ...settings:
import/resolver:
node:
extensions: ['.js', '.android.js', '.ios.js', '.web.js']
moduleDirectory:
- node_modules
- . # <-- app root

But since I believe “app” makes for a better alias than “src” (too generic), I had to battle a little more in order to get things working.

eslint-import-resolver-alias

// ./.eslintrc.yaml# ...settings:
import/resolver:
alias:
extensions: ['.js', '.android.js', '.ios.js', '.web.js']
map:
- ['app', './src']

Here we go. We’re all setup.

--

--