Cleaner imports with aliases in React & TypeScript
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 🥳