Oct 10, 2024

What are path aliases, how to configure?

Typescript

As projects grow in size and complexity, import statements can become really messy and ugly as well as hard to maintain or refactor. In such situations, normal relative path imports can become really really long and a pain for next developer.

A stitch in time saves nine.

Yep, that's right. Addressing this problem early can prevent it from becoming worse and more difficult to fix later.

#. Problem

Let's take a quick look at this piece of react code (not too big, but you will get the idea).

tsx
import React from 'react'; import { Button } from '../../../../components/button'; // ^^^^^^^^^^^^ long messy import function SomeComponent() { return <Button />; };

See how long that import was? well, for a small project, this wouldn't be a big deal, but when the project grows, changes it's structure, this will definitely become a pain to refactor.

#. Solution

You can setup a path alias in your project (will cover the configuration on next heading), it is like a shortcut for path imports. Take a look at below code with path alias.

tsx
import React from 'react'; import { Button } from '@components/button'; // ^ clean and concise import :) function SomeComponent() { return <Button />; };

See how just using path alias improved code quality, simplified imports and now it makes more sense right?

#. Configuration

You can configure path alias in the tsconfig.json file at the root of your typescript project.

To configure your path alias, simple add inside paths property in the compilerOptions object like below.

tsconfig.json
{ "compilerOptions": { "paths": { "@/*": ["./src/*"] } } }

The above code tells the Typescript compiler to resolve imports from alias @/* to directory ./src/*. Now you can use this alias to import anything from anywhere.

For example: If you wanna import a Button component from /src/components/button, even if you are on a deep directory, you can simple do it like this:

tsx
import { Button } from "@/components/Button"; // NOT // import { Button } from '../../../../components/button'; function App() { return ( <Button>Click Me</Button> ) }

See how easy it was to setup a path alias. You can add more alias to make it even more verbose, like:

tsconfig.json
{ "compilerOptions": { "baseUrl" : "./src", "paths": { "@components/*": ["./components/*"], "@ui/*": ["./components/common/ui/*"], "@pages/*": ["./pages/*"], "@hooks/*": ["./hooks/*"], "@api/*": ["./api/*"], "@utils/*": ["./utils/*"], } } }

Now it makes much more sense, right?

Well, this is just for typescript compiler. If you try to run code like this, it will show Cannot find module @/components/button, because we haven't yet configured for whichever bundler you are using, like vite, webpack, etc.

#. Vite

If you are using a vite + (react, solid, whichever it supports), you will have to repeat same steps in vite.config.(ts,js) file as well, like:

vite.config.ts
import { defineConfig } from 'vite'; import path from 'path'; export default defineConfig({ resolve: { alias: { '@': path.resolve(__dirname, 'src'), // add more alias if you want }, }, });

#. Webpack

If you are using Next.js, you don't have to configure it twice, because Next.js picks path aliases from tsconfig.json file and add those to webpack configuration automatically. So you can just skip this step.

webpack.config.js
module.exports = { resolve: { alias: { '@': path.resolve(__dirname, 'src'), // add more alias if you want }, extensions: ['.ts', '.tsx', '.js', '.jsx'], }, };

So that's basically it. Start using path aliases from the project starting stage, you will thank me later.