How To: Absolute imports in JavaScript
By Edward D'Souza (Feburary 20th, 2021)
Summary
In JavaScript, imports with relative paths going up more than one level are cumbersome.
import {dateFormat} from '../../../../src/lib/date';
You can make things better with aliases. If "src" is a top-level directory in your project, you can add an "@src" alias for "src" to let you write the above import like this:
import {dateFormat} from '@src/lib/date';
The steps to enable the above code are simple, but tedious. Because there is no standard way to specify aliases in JavaScript, you need to define the alias in the configuration of every environment that will be interpreting your JavaScript code. In a typical project these places would include:
- Webpack (webpack.config.js)
- Jest (jest.config.js)
- ESLint (.eslintrc.js)
- Visual Studio Code (jsconfig.json)
If you miss one of the above, e.g. leaving out Jest, you will encounter problems with environments not understanding your imports. To get the alias to work generally, you have to be thorough.
Detailed Guide
Below are instructions on how to update each of the above configs to add an alias mapping. I'm using the example of mapping a top-level directory named "src", but it will of course work with any directory. We are going to map the alias "@src" to "src".
Webpack (webpack.config.js)
In your Webpack config (e.g. webpack.config.js) find the "resolve" section, and then add an "alias" section under it. Then add the "@src" -> "src" alias like so:
const path = require("path");
module.exports = {
// ...
resolve: {
// ...
alias: {
"@src": path.resolve("src"),
},
// ..
},
// ...
};
Jest (jest.config.js)
module.exports = {
// ...
moduleNameMapper: {
"^@src/(.*)$": "<rootDir>/src/$1",
},
// ...
};
ESLint (.eslintrc.js)
For ESLint, you'll need to add two NPM packages:
-
eslint-plugin-import
-
eslint-import-resolver-alias
- Note that this second package is a plugin for the first. It adds support for aliases. There may be alternative packages available if this one doesn't work. See the eslint-plugin-import readme for more details. Apologies if this appears to be a house of cards at this point.
module.exports = {
// ...
settings: {
"import/resolver": {
alias: {
map: [["@src", "./src"]],
},
},
},
// ...
};
Visual Studio Code (jsconfig.json)
Unfortunately, editors need their own setup to understand the aliases. For VS Code, you can use the following jsconfig.json. For other editors, you'll have to do something similar. Note the very important last line to exclude node_modules.
{
"compilerOptions": {
"baseUrl": "./",
"paths": {
"@src/*": ["src/*"]
}
},
"exclude": ["node_modules"]
}
Final Advice
The lack of standardization for aliases is a mess. Given how popular they're becoming, hopefully we see some consolidation in this space. Until then, please treat these instructions as a rough guide. Good luck!