I recently configured an old project created with Create React App (CRA) to use path mapping/aliasing like @atoms
, @molecules
or @organisms
.
After using NextJS for a while, I got used to the idea of using @/
instead of just @
as a prefix for path mapping as it makes it a little bit clearer what is a path alias and what's not, like @apollo-client
or @fortawesome
.
The point in this post is how to enable your project to use @/
path mapping, but you can use the same settings to be able to use any other aliases, like @utils
or just utils
.
Configuring the path mapping
Considering you're using CRA, the first thing is to install @craco/craco
in your project to enable overriding original CRA's configuration.
To install @craco/craco
, just run:
yarn add -D @craco/craco
or
npm i -D @craco/craco
After installing @craco/craco
, in your package.json
, update your start
, build
and test
scripts to use craco
instead of react-scripts
, like recommended in CRACO's docs.
And then create a craco.config.js
file in your project's root adding your aliases to the alias
property of the webpack
property, where the key should be the alias's name and the value its path:
const path = require('path');
module.exports = {
webpack: {
alias: {
'@atoms': path.resolve(__dirname, './src/atoms'),
'@molecules': path.resolve(__dirname, './src/molecules'),
},
},
};
If you're using TypeScript, you should add those same path aliases to your tsconfig
file. In your tsconfig
file, look for compilerOptions
and add a paths
object like the following:
{
"compilerOptions": {
"paths": {
"@atoms/*": [
"./src/atoms/*"
],
"@molecules/*": [
"./src/molecules/*"
],
}
}
}
At this point, you should be able to import your components using the aliases you just defined:
import Button from '@atoms/Button';
import Table from '@molecules/Table'
Remember @atoms
and @molecules
are just examples. You can use any other aliases.
Allowing @/ path aliases
If you prefer to use @/
instead of @
as the alias prefix, you might face some trouble with ESLint as it might be complaining about missing file extensions on your imports:
Missing file extension for "@/pages/MainPage" eslint(import/extensions)
To allow ESLint to understand @/
aliases, you'll have to install the eslint-import-resolver-typescript
plugin.
Run
yarn add -D eslint-import-resolver-typescript
or
npm i -D eslint-import-resolver-typescript
Then, go to your .eslintrc
file and add the following configuration within the settings
section:
"settings": {
"import/resolver": {
"typescript": {}
}
}
Now ESLint should've stopped complaining about missing file extensions. If you're still getting a warning about extensions, check your import/extensions
rule inside the rules
section. You can read more about this rule here.
đ Bonus round: enabling Jest to use path aliases
Again, considering you're using TypeScript, to allow Jest to read your path aliases you'll have to install and configure ts-jest
.
Run
yarn add -D ts-jest
or
npm i -D ts-jest
After installing ts-jest
, update your craco.config.js
file like the following, telling Jest to use the paths configured in your tsconfig
file:
const path = require('path');
const { pathsToModuleNameMapper } = require('ts-jest');
const { compilerOptions } = require('./tsconfig.json');
module.exports = {
webpack: {
alias: {
'@atoms': path.resolve(__dirname, './src/atoms'),
'@molecules': path.resolve(__dirname, './src/molecules'),
},
},
jest: {
configure: {
preset: 'ts-jest',
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, {
prefix: '<rootDir>/',
}),
},
},
};
That's it! You now should be able to use path mapping in your project, including your unit tests and also using @/
path aliases.
Top comments (2)
After reading several tutorials, it's your which helped me to solve my problem.
I saw in a tutorial where he used one line in craco.config.js like this
'@' : path.resolve(__dirname,'src'),
Is it possible?!
I couldn't make it work.
Hey, @kiswayodg . I guess you can use something like the following in your
tsconfig
:And the following in your
craco.config
:I'm not able to test it right now, but tell me if this works for you.
Glad to help!