HomeProjects
 
  

Cleaner imports with aliases in React & TypeScript

July 3, 2022

The problem with relative imports

As a project's been growing, you might've found yourself making imports like this:

import { someUtil } from '../../../../src/utils';
import defaultExport, { SomeModule } from '../../../src/modules/dummy-module';

This can quickly get out of hand, resulting in many chaotic imports from some deeply nested folders. This would get a lot cleaner, if we could do something like this:

import { someUtil } from '@/utils';
import defaultExport, { SomeModule } from '@dummy-module';

We essentially mapped @ to src folder and @dummy-module to src/modules/dummy-module folder which allowed us to reference them directly using their alias.

Configuring aliased imports

TypeScript configuration

In order for TypeScript to become aware of our alias paths, we must define them inside our tsconfig.json file, under compilerOptions:

// tsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
...,
"paths": {
"@/*": ["src/*"], // 👈 This line allows us to import from folders inside "src" folder using "@"
"@dummy-module": ["src/modules/dummy-module"], // 👈 This line allows us to import from the "dummy-module" folder itself using "@dummy-module"
"@dummy-module/*": ["src/modules/dummy-module/*"] // 👈 This line allows us to import from folders inside "src/modules/dummy-module" folder using "@dummy-module"
}
},
...
}

We are now able to import using the above aliases. In case TypeScript still complains about your imports, then create a separate tsconfig.paths.json file next to tsconfig.json (inside root directory), to extend your base config from:

// tsconfig.paths.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"], // 👈 This line allows us to import from folders inside "src" folder using "@"
"@dummy-module": ["src/modules/dummy-module"], // 👈 This line allows us to import from the "dummy-module" folder itself using "@dummy-module"
"@dummy-module/*": ["src/modules/dummy-module/*"] // 👈 This line allows us to import from folders inside "src/modules/dummy-module" folder using "@dummy-module"
}
}
}

and modify tsconfig.json like this:

// tsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
... 👈 Remove "paths" option
},
"extends": "./tsconfig.paths.json" // 👈 Add this line
}

Webpack configuration

In a react app, you've most likely used create-react-app as a scaffold. So you need to override its internal webpack configuration, in order to let the bundler know how to resolve your aliases during build time. To do that without ejecting, you can use craco:

npm i @craco/craco

or

yarn add @craco/craco

Next, create a craco.config.js file at your project’s root and paste this code:

const path = require('path');
module.exports = {
webpack: {
alias: {
'@': path.resolve(__dirname, 'src'),
'@dummy-module': path.resolve(__dirname, 'src/modules/dummy-module'),
},
},
};

Finally, replace react-scripts with craco inside package.json file:

"scripts": {
"start": "craco start",
"build": "craco build",
"test": "craco test",
"eject": "craco eject"
}

and restart your app:

yarn start

And that's all folks 🥳

Emmanouil Liakos

Emmanouil Liakos

Software Engineer

 

 

© 2023. Made with ♡ by me :)