DEV Community

Tom Tillistrand
Tom Tillistrand

Posted on

Aliasing paths in Vite projects w/ TypeScript

Aliasing paths can be a really handy way of referencing key directories in your project within deeply nested files. For example, take a look at the structure of this fictitious Vite TypeScript project:

.
├── index.html
├── package-lock.json
├── package.json
├── public
│   └── vite.svg
├── src
│   ├── App.tsx
│   ├── assets
│   │   ├── image.png
│   ├── components
│   │   ├── ComponentA
│   │   │   └── ComponentA.tsx
│   ├── main.tsx
│   └── vite-env.d.ts
├── tsconfig.json
├── tsconfig.node.json
└── vite.config.ts
Enter fullscreen mode Exit fullscreen mode

Let's say we wanted to import image.png from ComponentA.tsx. Our import would look like this:

import image from '../../../assets/image.png';
Enter fullscreen mode Exit fullscreen mode

Not so nice. With deeply nested structures you can end up with even longer paths. It'd be a lot nicer if we could just alias the key folders and do something like this instead:

import image from `@assets/image.png`
Enter fullscreen mode Exit fullscreen mode

Let's see how we can do that in Vite.

Step 1 - Add aliases to vite.config.ts

Our first step is to register aliases with Vite (and Rollup, which Vite uses under the hood). We can do that in our vite.config.ts:

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import path from 'path';

// https://vitejs.dev/config/
export default defineConfig({
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
      '@assets': path.resolve(__dirname, './src/assets'),
      '@components': path.resolve(__dirname, './src/components'),
    },
  },
  plugins: [react()]
})
Enter fullscreen mode Exit fullscreen mode

Side note - make sure to npm install -D @types/node in order to avoid issues with importing path and using __dirname

Now Vite knows to reference the src directory whenever we use @ in our imports.

Step 2 - Add aliases to tsconfig.json

The TypeScript compiler also needs to know about our aliases so that it can compile all of our imported files. Let's update our tsconfig.json accordingly:

{
  "compilerOptions": {
    // ... your other compiler options
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"],
      "@components/*": ["src/components/*"],
      "@assets/*": ["src/assets/*"]
    },
  },
  "include": ["src"],
  "references": [{ "path": "./tsconfig.node.json" }]
}
Enter fullscreen mode Exit fullscreen mode

There's a slight syntax difference between what we added in our vite.config.ts, but the idea is the same. There's also a baseUrl property to specify what our paths are relative to.


That's about all there is to it. Now you can use @, @assets, and @components in your import paths. I kept this example to three aliases for simplicity's sake, but feel free to use as many as your project calls for. Enjoy!

Top comments (12)

Collapse
 
ajeetkumarrauniyar profile image
Ajeet Kumar

I am trying to do so but didn't worked. I am using JavaScript, instead of Typescript.

vite.config.json

import path from "path";
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

const __filename = import.meta.url;
const __dirname = path.dirname(__filename);

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  optimizeDeps: {
    exclude: ["js-big-decimal"],
  },
  server: {
    port: 8000,
  },
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src'),
      '@assets': path.resolve(__dirname, './src/assets'),
      '@components': path.resolve(__dirname, './src/components'),
    },
  },
});

Enter fullscreen mode Exit fullscreen mode

and

package.json

{
  "name": "mern-wp-lms",
  "private": true,
  "version": "1.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite --host",
    "build": "vite build",
    "lint": "eslint . --ext js,jsx --report-unused-disable-directives --max-warnings 5",
    "preview": "vite preview"
  },
  "dependencies": {
    //  existing dependencies
  },
  "devDependencies": {
    //  existing devDependencies
  },
  "resolve-path-alias": {
    "alias": {
      "@/*": "src/*",
      "@components/*": "src/components/*",
      "@assets/*": "src/assets/*"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Imported as import Header from "@components/Header";

Also, I had installed @types/node as per the instructions.

But still receiving this error

Failed to resolve import "@components/Header" from "src/pages/contacts/index.jsx". Does the file exist?
Enter fullscreen mode Exit fullscreen mode

Please Help!

Collapse
 
henryzarza profile image
Henry Zarza

As you're not using TypeScript, you should create a file named jsconfig.json in the root folder of your app and put the config there, something like this:

{
"compilerOptions": {
"baseUrl": ".",
"target": "es6",
"paths": {
"@/*": "src/*",
"@components/*": "src/components/*",
"@assets/*": "src/assets/*"
}
},
"exclude": ["node_modules"]
}

Collapse
 
ajeetkumarrauniyar profile image
Ajeet Kumar

Thank you for the reply. I have figured out the solution here... stackoverflow.com/questions/777661...

Collapse
 
danielrios549 profile image
Daniel Rios

Is there an option to use these alias in path parameter of a function? I would like to use in a fs.readdirSync to not enter the whole path

Collapse
 
emmanuelisenah profile image
Emmanuel Isenah

Finally got it working. Thank you

Collapse
 
8ctopotamus profile image
Josh

Worked perfectly! Thanks for sharing! 😎

Collapse
 
m3cv1no profile image
Majd Sami Hemud

Thank you so much, it was really helpful 😁🙌

Collapse
 
tranduchoa profile image
Trần Đức Hòa

Great instructions! Thanks man.

Collapse
 
hadisamadzad profile image
Hadi Samadzad

After one whole day of testing many sets of configurations, finally you helped me, Thank you

Collapse
 
minadimyan profile image
Mina Demian

Didn't work for me, this did: stackoverflow.com/questions/660436...

Collapse
 
devabsiddik profile image
Ab Siddik

Thanks a lot bro

Collapse
 
quoczuong profile image
Zuong

I created an account just to say thank you