Fixing import path hell (React Native, ESLint, VS Code)
Jun 11, 2019I 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/*"]
}
}
}
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.
If you enjoyed this article, give it a clap on Medium.